New feature: Code changes for project support

Signed-off-by: Philip Joseph <philip.joseph@riftio.com>
diff --git a/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/engine.py b/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/engine.py
index d71aefc..d43a3d6 100644
--- a/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/engine.py
+++ b/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/engine.py
@@ -106,6 +106,7 @@
             log,
             dts,
             loop,
+            project,
             nsr_id,
             monp_id,
             scaling_criteria,
@@ -143,6 +144,7 @@
                 self.log,
                 self.dts,
                 self.loop,
+                project,
                 self.nsr_id,
                 self.monp_id,
                 callback=self.add_value)
@@ -236,6 +238,7 @@
             log,
             dts,
             loop,
+            project,
             nsr_id,
             nsd_id,
             scaling_group_name,
@@ -258,6 +261,7 @@
         self.loop = loop
         self.log = log
         self.dts = dts
+        self.project = project
         self.nsd_id = nsd_id
         self.nsr_id = nsr_id
         self.scaling_group_name = scaling_group_name
@@ -270,6 +274,7 @@
                                 self.log,
                                 self.dts,
                                 self.loop,
+                                self.project,
                                 self.nsr_id,
                                 callback=self.handle_nsr_monp)
 
@@ -311,6 +316,7 @@
                         self.log,
                         self.dts,
                         self.loop,
+                        self.project,
                         self.nsr_id,
                         monp.id,
                         cri,
diff --git a/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/rwautoscaler.py b/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/rwautoscaler.py
index affa579..98e37e6 100644
--- a/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/rwautoscaler.py
+++ b/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/rwautoscaler.py
@@ -1,6 +1,6 @@
 """
-# 
-#   Copyright 2016 RIFT.IO Inc
+#
+#   Copyright 2016-2017 RIFT.IO Inc
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -39,10 +39,149 @@
 import rift.mano.cloud
 import rift.mano.dts as subscriber
 import rift.tasklets
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+    )
 
 
+class AutoScalerProject(ManoProject, engine.ScalingPolicy.Delegate):
 
-class AutoScalerTasklet(rift.tasklets.Tasklet, engine.ScalingPolicy.Delegate):
+    def __init__(self, name, tasklet, **kw):
+        super(AutoScalerProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self.store = None
+        self.monparam_store = None
+        self.nsr_sub = None
+        self.nsr_monp_subscribers = {}
+        self.instance_id_store = collections.defaultdict(list)
+
+        self.store = subscriber.SubscriberStore.from_project(self)
+        self.nsr_sub = subscriber.NsrCatalogSubscriber(self.log, self.dts, self.loop,
+                                                       self, self.handle_nsr)
+
+    def deregister(self):
+        self.log.debug("De-register project {}".format(self.name))
+        self.nsr_sub.deregister()
+        self.store.deregister()
+
+
+    @asyncio.coroutine
+    def register (self):
+        self.log.debug("creating vnfr subscriber")
+        yield from self.store.register()
+        yield from self.nsr_sub.register()
+
+    def scale_in(self, scaling_group_name, nsr_id):
+        """Delegate callback
+
+        Args:
+            scaling_group_name (str): Scaling group name to be scaled in
+            nsr_id (str): NSR id
+
+        """
+        self.log.info("Sending a scaling-in request for {} in NSR: {}".format(
+                scaling_group_name,
+                nsr_id))
+
+        @asyncio.coroutine
+        def _scale_in():
+            instance_id = self.instance_id_store[(scaling_group_name, nsr_id)].pop()
+
+            # Trigger an rpc
+            rpc_ip = NsrYang.YangInput_Nsr_ExecScaleIn.from_dict({
+                'project_name': self.name,
+                'nsr_id_ref': nsr_id,
+                'instance_id': instance_id,
+                'scaling_group_name_ref': scaling_group_name})
+
+            rpc_out = yield from self.dts.query_rpc(
+                        "/nsr:exec-scale-in",
+                        0,
+                        rpc_ip)
+
+        self.loop.create_task(_scale_in())
+
+    def scale_out(self, scaling_group_name, nsr_id):
+        """Delegate callback for scale out requests
+
+        Args:
+            scaling_group_name (str): Scaling group name
+            nsr_id (str): NSR ID
+        """
+        self.log.info("Sending a scaling-out request for {} in NSR: {}".format(
+                scaling_group_name,
+                nsr_id))
+
+        @asyncio.coroutine
+        def _scale_out():
+            # Trigger an rpc
+            rpc_ip = NsrYang.YangInput_Nsr_ExecScaleOut.from_dict({
+                'project_name': self.name,
+                'nsr_id_ref': nsr_id ,
+                'scaling_group_name_ref': scaling_group_name})
+
+            itr = yield from self.dts.query_rpc("/nsr:exec-scale-out", 0, rpc_ip)
+
+            key = (scaling_group_name, nsr_id)
+            for res in itr:
+                result = yield from res
+                rpc_out = result.result
+                self.instance_id_store[key].append(rpc_out.instance_id)
+
+                self.log.info("Created new scaling group {} with instance id {}".format(
+                        scaling_group_name,
+                        rpc_out.instance_id))
+
+        self.loop.create_task(_scale_out())
+
+
+    def handle_nsr(self, nsr, action):
+        """Callback for NSR opdata changes. Creates a publisher for every
+        NS that moves to config state.
+
+        Args:
+            nsr (RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr): Ns Opdata
+            action (rwdts.QueryAction): Action type of the change.
+        """
+        def nsr_create():
+            if nsr.config_status == "configured" and nsr.ns_instance_config_ref not in self.nsr_monp_subscribers:
+                nsr_id = nsr.ns_instance_config_ref
+                self.nsr_monp_subscribers[nsr_id] = []
+                nsd = self.store.get_nsd(nsr.nsd_ref)
+                @asyncio.coroutine
+                def task():
+                    for scaling_group in nsd.scaling_group_descriptor:
+                        for policy_cfg in scaling_group.scaling_policy:
+                            policy = engine.ScalingPolicy(
+                                self.log, self.dts, self.loop, self,
+                                nsr.ns_instance_config_ref,
+                                nsr.nsd_ref,
+                                scaling_group.name,
+                                policy_cfg,
+                                self.store,
+                                delegate=self)
+                            self.nsr_monp_subscribers[nsr_id].append(policy)
+                            yield from policy.register()
+
+                self.loop.create_task(task())
+
+
+        def nsr_delete():
+            if nsr.ns_instance_config_ref in self.nsr_monp_subscribers:
+                policies = self.nsr_monp_subscribers[nsr.ns_instance_config_ref]
+                for policy in policies:
+                    policy.deregister()
+                del self.nsr_monp_subscribers[nsr.ns_instance_config_ref]
+
+        if action in [rwdts.QueryAction.CREATE, rwdts.QueryAction.UPDATE]:
+            nsr_create()
+        elif action == rwdts.QueryAction.DELETE:
+            nsr_delete()
+
+
+class AutoScalerTasklet(rift.tasklets.Tasklet):
     """The main task of this Tasklet is to listen for NSR changes and once the
     NSR is configured, ScalingPolicy is created.
     """
@@ -50,12 +189,9 @@
 
         try:
             super().__init__(*args, **kwargs)
-            self.store = None
-            self.monparam_store = None
 
-            self.nsr_sub = None
-            self.nsr_monp_subscribers = {}
-            self.instance_id_store = collections.defaultdict(list)
+            self._project_handler = None
+            self.projects = {}
 
         except Exception as e:
             self.log.exception(e)
@@ -72,9 +208,6 @@
                 self.on_dts_state_change
                 )
 
-        self.store = subscriber.SubscriberStore.from_tasklet(self)
-        self.nsr_sub = subscriber.NsrCatalogSubscriber(self.log, self.dts, self.loop, self.handle_nsr)
-
         self.log.debug("Created DTS Api GI Object: %s", self.dts)
 
     def stop(self):
@@ -85,9 +218,9 @@
 
     @asyncio.coroutine
     def init(self):
-        self.log.debug("creating vnfr subscriber")
-        yield from self.store.register()
-        yield from self.nsr_sub.register()
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, AutoScalerProject)
+        self.project_handler.register()
 
     @asyncio.coroutine
     def run(self):
@@ -124,107 +257,3 @@
         if next_state is not None:
             self.dts.handle.set_state(next_state)
 
-    def scale_in(self, scaling_group_name, nsr_id):
-        """Delegate callback
-
-        Args:
-            scaling_group_name (str): Scaling group name to be scaled in
-            nsr_id (str): NSR id
-
-        """
-        self.log.info("Sending a scaling-in request for {} in NSR: {}".format(
-                scaling_group_name,
-                nsr_id))
-
-        @asyncio.coroutine
-        def _scale_in():
-            instance_id = self.instance_id_store[(scaling_group_name, nsr_id)].pop()
-
-            # Trigger an rpc
-            rpc_ip = NsrYang.YangInput_Nsr_ExecScaleIn.from_dict({
-                'nsr_id_ref': nsr_id,
-                'instance_id': instance_id,
-                'scaling_group_name_ref': scaling_group_name})
-
-            rpc_out = yield from self.dts.query_rpc(
-                        "/nsr:exec-scale-in",
-                        0,
-                        rpc_ip)
-
-        self.loop.create_task(_scale_in())
-
-    def scale_out(self, scaling_group_name, nsr_id):
-        """Delegate callback for scale out requests
-
-        Args:
-            scaling_group_name (str): Scaling group name
-            nsr_id (str): NSR ID
-        """
-        self.log.info("Sending a scaling-out request for {} in NSR: {}".format(
-                scaling_group_name,
-                nsr_id))
-
-        @asyncio.coroutine
-        def _scale_out():
-            # Trigger an rpc
-            rpc_ip = NsrYang.YangInput_Nsr_ExecScaleOut.from_dict({
-                'nsr_id_ref': nsr_id ,
-                'scaling_group_name_ref': scaling_group_name})
-
-            itr = yield from self.dts.query_rpc("/nsr:exec-scale-out", 0, rpc_ip)
-
-            key = (scaling_group_name, nsr_id)
-            for res in itr:
-                result = yield from res
-                rpc_out = result.result
-                self.instance_id_store[key].append(rpc_out.instance_id)
-
-                self.log.info("Created new scaling group {} with instance id {}".format(
-                        scaling_group_name,
-                        rpc_out.instance_id))
-
-        self.loop.create_task(_scale_out())
-
-
-    def handle_nsr(self, nsr, action):
-        """Callback for NSR opdata changes. Creates a publisher for every
-        NS that moves to config state.
-
-        Args:
-            nsr (RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr): Ns Opdata
-            action (rwdts.QueryAction): Action type of the change.
-        """
-        def nsr_create():
-            if nsr.config_status == "configured" and nsr.ns_instance_config_ref not in self.nsr_monp_subscribers:
-                nsr_id = nsr.ns_instance_config_ref
-                self.nsr_monp_subscribers[nsr_id] = []
-                nsd = self.store.get_nsd(nsr.nsd_ref)
-                @asyncio.coroutine
-                def task():
-                    for scaling_group in nsd.scaling_group_descriptor:
-                        for policy_cfg in scaling_group.scaling_policy:
-                            policy = engine.ScalingPolicy(
-                                self.log, self.dts, self.loop,
-                                nsr.ns_instance_config_ref,
-                                nsr.nsd_ref,
-                                scaling_group.name,
-                                policy_cfg,
-                                self.store,
-                                delegate=self)
-                            self.nsr_monp_subscribers[nsr_id].append(policy)
-                            yield from policy.register()
-
-                self.loop.create_task(task())
-
-
-        def nsr_delete():
-            if nsr.ns_instance_config_ref in self.nsr_monp_subscribers:
-                policies = self.nsr_monp_subscribers[nsr.ns_instance_config_ref]
-                for policy in policies:
-                    policy.deregister()
-                del self.nsr_monp_subscribers[nsr.ns_instance_config_ref]
-
-        if action in [rwdts.QueryAction.CREATE, rwdts.QueryAction.UPDATE]:
-            nsr_create()
-        elif action == rwdts.QueryAction.DELETE:
-            nsr_delete()
diff --git a/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/subscribers.py b/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/subscribers.py
index 04185b6..f96a832 100644
--- a/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/subscribers.py
+++ b/rwlaunchpad/plugins/rwautoscaler/rift/tasklets/rwautoscaler/subscribers.py
@@ -1,6 +1,6 @@
 
-# 
-#   Copyright 2016 RIFT.IO Inc
+#
+#   Copyright 2016-2017 RIFT.IO Inc
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -20,21 +20,18 @@
 
 class NsrMonParamSubscriber(mano_dts.AbstractOpdataSubscriber):
     """Registers for NSR monitoring parameter changes.
-    
+
     Attributes:
         monp_id (str): Monitoring Param ID
         nsr_id (str): NSR ID
     """
-    def __init__(self, log, dts, loop, nsr_id, monp_id=None, callback=None):
-        super().__init__(log, dts, loop, callback)
+    def __init__(self, log, dts, loop, project, nsr_id, monp_id=None, callback=None):
+        super().__init__(log, dts, loop, project, callback)
         self.nsr_id = nsr_id
         self.monp_id = monp_id
 
     def get_xpath(self):
-        return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
+        return self.project.add_project(("D,/nsr:ns-instance-opdata/nsr:nsr" +
             "[nsr:ns-instance-config-ref='{}']".format(self.nsr_id) +
             "/nsr:monitoring-param" +
-            ("[nsr:id='{}']".format(self.monp_id) if self.monp_id else ""))
-
-
-
+            ("[nsr:id='{}']".format(self.monp_id) if self.monp_id else "")))
diff --git a/rwlaunchpad/plugins/rwautoscaler/test/utest_autoscaler_dts.py b/rwlaunchpad/plugins/rwautoscaler/test/utest_autoscaler_dts.py
index c00ca11..edc7a9e 100644
--- a/rwlaunchpad/plugins/rwautoscaler/test/utest_autoscaler_dts.py
+++ b/rwlaunchpad/plugins/rwautoscaler/test/utest_autoscaler_dts.py
@@ -42,8 +42,8 @@
         )
 
 
-ScalingCriteria = NsdYang.YangData_Nsd_NsdCatalog_Nsd_ScalingGroupDescriptor_ScalingPolicy_ScalingCriteria
-ScalingPolicy = NsdYang.YangData_Nsd_NsdCatalog_Nsd_ScalingGroupDescriptor_ScalingPolicy
+ScalingCriteria = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_ScalingGroupDescriptor_ScalingPolicy_ScalingCriteria
+ScalingPolicy = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_ScalingGroupDescriptor_ScalingPolicy
 
 
 class MockDelegate(engine.ScalingCriteria.Delegate):
@@ -73,7 +73,7 @@
     def __call__(self):
         store = mock.MagicMock()
 
-        mock_vnfd =  RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd.from_dict({
+        mock_vnfd =  RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd.from_dict({
             'id': "1",
             'monitoring_param': [
                 {'description': 'no of ping requests',
@@ -98,12 +98,12 @@
 
         store.get_vnfd = mock.MagicMock(return_value=mock_vnfd)
 
-        mock_vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict({'id': '1'})
-        mock_vnfr.vnfd = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict({'id': '1'})
+        mock_vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.from_dict({'id': '1'})
+        mock_vnfr.vnfd = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vnfd.from_dict({'id': '1'})
 
         store.get_vnfr = mock.MagicMock(return_value=mock_vnfr)
 
-        mock_nsr = RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr.from_dict({
+        mock_nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr.from_dict({
             'ns_instance_config_ref': "1",
             'name_ref': "Foo",
             'nsd_ref': '1',
@@ -138,7 +138,7 @@
         scale_in_val = 100
         scale_out_val = 200
 
-        mock_nsd = RwNsdYang.YangData_Nsd_NsdCatalog_Nsd.from_dict({
+        mock_nsd = RwNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd.from_dict({
             'id': '1',
             'monitoring_param': (monp_cfg if not self.legacy else []),
             'constituent_vnfd': [{'member_vnf_index': 1,
@@ -206,13 +206,13 @@
     def _populate_mock_values(self, criterias, nsr_id, floor, ceil):
         # Mock publish
         # Verify Scale in AND operator
-        NsMonParam = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_MonitoringParam
+        NsMonParam = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_MonitoringParam
 
         publisher = rift.test.dts.DescriptorPublisher(self.log, self.dts, self.loop)
 
         for criteria in criterias:
             monp_id = criteria.ns_monitoring_param_ref
-            w_xpath = "D,/nsr:ns-instance-opdata/nsr:nsr"
+            w_xpath = "D,/rw-project:project/nsr:ns-instance-opdata/nsr:nsr"
             w_xpath = w_xpath + "[nsr:ns-instance-config-ref='{}']/nsr:monitoring-param".format(nsr_id)
             xpath =  w_xpath + "[nsr:id ='{}']".format(monp_id)
 
diff --git a/rwlaunchpad/plugins/rwimagemgr/rift/imagemgr/client.py b/rwlaunchpad/plugins/rwimagemgr/rift/imagemgr/client.py
index 10df45b..42185ae 100644
--- a/rwlaunchpad/plugins/rwimagemgr/rift/imagemgr/client.py
+++ b/rwlaunchpad/plugins/rwimagemgr/rift/imagemgr/client.py
@@ -48,7 +48,7 @@
         self._loop = loop
         self._dts = dts
 
-    def create_job(self, image_name, image_checksum, cloud_account_names=None):
+    def create_job(self, image_name, image_checksum, project, cloud_account_names=None):
         """ Create an image upload_job and return an UploadJob instance
 
         Arguments:
@@ -62,6 +62,7 @@
         """
         create_job_msg = RwImageMgmtYang.CreateUploadJob.from_dict({
             "onboarded_image": {
+                "project_name": project.name,
                 "image_name": image_name,
                 "image_checksum": image_checksum,
                 }
@@ -81,9 +82,9 @@
 
             job_id = rpc_result.job_id
 
-        return UploadJob(self._log, self._loop, self._dts, job_id)
+        return UploadJob(self._log, self._loop, self._dts, job_id, project)
 
-    def create_job_threadsafe(self, image_name, image_checksum, cloud_account_names=None):
+    def create_job_threadsafe(self, image_name, image_checksum, project, cloud_account_names=None):
         """ A thread-safe, syncronous wrapper for create_job """
         future = concurrent.futures.Future()
 
@@ -96,7 +97,7 @@
 
         def add_task():
             task = self._loop.create_task(
-                    self.create_job(image_name, image_checksum, cloud_account_names)
+                    self.create_job(image_name, image_checksum, project, cloud_account_names)
                     )
             task.add_done_callback(on_done)
 
@@ -106,11 +107,12 @@
 
 class UploadJob(object):
     """ A handle for a image upload job """
-    def __init__(self, log, loop, dts, job_id):
+    def __init__(self, log, loop, dts, job_id, project):
         self._log = log
         self._loop = loop
         self._dts = dts
         self._job_id = job_id
+        self._project = project
 
     @asyncio.coroutine
     def wait_until_complete(self):
@@ -122,12 +124,11 @@
             UploadJobCancelled: The upload job was cancelled
         """
         self._log.debug("waiting for upload job %s to complete", self._job_id)
+        xpath = self._project.add_project("D,/rw-image-mgmt:upload-jobs/" +
+                                          "rw-image-mgmt:job[rw-image-mgmt:id='{}']".
+                                          format(self._job_id))
         while True:
-            query_iter = yield from self._dts.query_read(
-                "D,/rw-image-mgmt:upload-jobs/rw-image-mgmt:job[rw-image-mgmt:id='{}']".format(
-                    self._job_id
-                )
-            )
+            query_iter = yield from self._dts.query_read(xpath)
             job_status_msg = None
             for fut_resp in query_iter:
                 job_status_msg = (yield from fut_resp).result
diff --git a/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/tasklet.py b/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/tasklet.py
index 027e582..f3ba2ed 100644
--- a/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/tasklet.py
+++ b/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/tasklet.py
@@ -22,6 +22,13 @@
 
 import rift.tasklets
 import rift.mano.cloud
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectConfigCallbacks,
+    ProjectHandler,
+    get_add_delete_update_cfgs,
+    DEFAULT_PROJECT,
+    )
 
 from . import glance_proxy_server
 from . import glance_client
@@ -53,16 +60,18 @@
 
 
 class CloudAccountDtsHandler(object):
-    def __init__(self, log, dts, log_hdl):
+    def __init__(self, log, dts, log_hdl, project):
         self._dts = dts
         self._log = log
         self._log_hdl = log_hdl
         self._cloud_cfg_subscriber = None
+        self._project = project
 
     def register(self, on_add_apply, on_delete_apply):
-        self._log.debug("creating cloud account config handler")
+        self._log.debug("Project {}: creating cloud account config handler".
+                        format(self._project.name))
         self._cloud_cfg_subscriber = rift.mano.cloud.CloudAccountConfigSubscriber(
-                self._dts, self._log, self._log_hdl,
+                self._dts, self._log, self._log_hdl, self._project,
                 rift.mano.cloud.CloudAccountConfigCallbacks(
                     on_add_apply=on_add_apply,
                     on_delete_apply=on_delete_apply,
@@ -70,6 +79,11 @@
                 )
         self._cloud_cfg_subscriber.register()
 
+    def deregister(self):
+        self._log.debug("Project {}: Removing cloud account config handler".
+                        format(self._project.name))
+        self._cloud_cfg_subscriber.deregister()
+
 
 def openstack_image_to_image_info(openstack_image):
     """Convert the OpenstackImage to a ImageInfo protobuf message
@@ -95,19 +109,21 @@
 
 class ImageDTSShowHandler(object):
     """ A DTS publisher for the upload-jobs data container """
-    def __init__(self, log, loop, dts, job_controller):
+    def __init__(self, log, loop, dts, job_controller, project):
         self._log = log
         self._loop = loop
         self._dts = dts
         self._job_controller = job_controller
+        self._project = project
 
         self._subscriber = None
 
+    def get_xpath(self):
+        return self._project.add_project("D,/rw-image-mgmt:upload-jobs")
+
     @asyncio.coroutine
     def register(self):
         """ Register as a publisher and wait for reg_ready to complete """
-        def get_xpath():
-            return "D,/rw-image-mgmt:upload-jobs"
 
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
@@ -119,7 +135,7 @@
 
             xact_info.respond_xpath(
                     rwdts.XactRspCode.ACK,
-                    xpath=get_xpath(),
+                    xpath=self.get_xpath(),
                     msg=jobs_pb_msg,
                     )
 
@@ -130,7 +146,7 @@
             reg_event.set()
 
         self._subscriber = yield from self._dts.register(
-                xpath=get_xpath(),
+                xpath=self.get_xpath(),
                 handler=rift.tasklets.DTS.RegistrationHandler(
                     on_prepare=on_prepare,
                     on_ready=on_ready,
@@ -141,9 +157,18 @@
         yield from reg_event.wait()
 
 
+    def deregister(self):
+        self._log.debug("Project {}: De-register show image handler".
+                        format(self._project.name))
+        if self._subscriber:
+            self._subscriber.delete_element(self.get_xpath())
+            self._subscriber.deregister()
+            self._subscriber = None
+
 class ImageDTSRPCHandler(object):
     """ A DTS publisher for the upload-job RPC's """
-    def __init__(self, log, loop, dts, accounts, glance_client, upload_task_creator, job_controller):
+    def __init__(self, log, loop, dts, accounts, glance_client,
+                 upload_task_creator, job_controller, project):
         self._log = log
         self._loop = loop
         self._dts = dts
@@ -151,8 +176,10 @@
         self._glance_client = glance_client
         self._upload_task_creator = upload_task_creator
         self._job_controller = job_controller
+        self._project = project
 
-        self._subscriber = None
+        self._create = None
+        self._cancel = None
 
     @asyncio.coroutine
     def _register_create_upload_job(self):
@@ -164,6 +191,10 @@
             create_msg = msg
 
             account_names = create_msg.cloud_account
+
+            if not self._project.rpc_check(msg, xact_info):
+                return
+
             # If cloud accounts were not specified, upload image to all cloud account
             if not account_names:
                 account_names = list(self._accounts.keys())
@@ -217,14 +248,14 @@
         def on_ready(_, status):
             reg_event.set()
 
-        self._subscriber = yield from self._dts.register(
-                xpath="I," + get_xpath(),
-                handler=rift.tasklets.DTS.RegistrationHandler(
-                    on_prepare=on_prepare,
-                    on_ready=on_ready,
-                    ),
-                flags=rwdts.Flag.PUBLISHER,
-                )
+        self._create = yield from self._dts.register(
+            xpath="I," + get_xpath(),
+            handler=rift.tasklets.DTS.RegistrationHandler(
+                on_prepare=on_prepare,
+                on_ready=on_ready,
+            ),
+            flags=rwdts.Flag.PUBLISHER,
+        )
 
         yield from reg_event.wait()
 
@@ -235,6 +266,9 @@
 
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
+            if not self._project.rpc_check(msg, xact_info):
+                return
+
             if not msg.has_field("job_id"):
                 self._log.error("cancel-upload-job missing job-id field.")
                 xact_info.respond_xpath(rwdts.XactRspCode.NACK)
@@ -256,14 +290,14 @@
         def on_ready(_, status):
             reg_event.set()
 
-        self._subscriber = yield from self._dts.register(
-                xpath="I," + get_xpath(),
-                handler=rift.tasklets.DTS.RegistrationHandler(
-                    on_prepare=on_prepare,
-                    on_ready=on_ready,
-                    ),
-                flags=rwdts.Flag.PUBLISHER,
-                )
+        self._cancel = yield from self._dts.register(
+            xpath="I," + get_xpath(),
+            handler=rift.tasklets.DTS.RegistrationHandler(
+                on_prepare=on_prepare,
+                on_ready=on_ready,
+            ),
+            flags=rwdts.Flag.PUBLISHER,
+        )
 
         yield from reg_event.wait()
 
@@ -273,16 +307,28 @@
         yield from self._register_create_upload_job()
         yield from self._register_cancel_upload_job()
 
+    def deregister(self):
+        self._log.debug("Project {}: Deregister image rpc handlers".
+                        format(self._project.name))
+        if self._create:
+            self._create.deregister()
+            self._create = None
+
+        if self._cancel:
+            self._cancel.deregister()
+            self._cancel = None
+
 
 class GlanceClientUploadTaskCreator(object):
     """ This class creates upload tasks using configured cloud accounts and
     configured image catalog glance client """
 
-    def __init__(self, log, loop, accounts, glance_client):
+    def __init__(self, log, loop, accounts, glance_client, project):
         self._log = log
         self._loop = loop
         self._accounts = accounts
         self._glance_client = glance_client
+        self._project = project
 
     @asyncio.coroutine
     def create_tasks(self, account_names, image_id=None, image_name=None, image_checksum=None):
@@ -397,6 +443,78 @@
             create_msg.image_checksum if "image_checksum" in create_msg else None)
             )
 
+class ImageMgrProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(ImageMgrProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+        try:
+            self.glance_client = kw['client']
+        except KeyError as e:
+            self._log.exception("kw {}: {}".format(kw, e))
+
+        self.cloud_cfg_subscriber = None
+        self.job_controller = None
+        self.task_creator = None
+        self.rpc_handler = None
+        self.show_handler = None
+
+        self.cloud_accounts = {}
+
+    @asyncio.coroutine
+    def register(self):
+        try:
+            self.log.debug("creating cloud account handler")
+            self.cloud_cfg_subscriber = CloudAccountDtsHandler(self._log,
+                                                               self._dts,
+                                                               self._log_hdl,
+                                                               self)
+            self.cloud_cfg_subscriber.register(
+                    self.on_cloud_account_create,
+                    self.on_cloud_account_delete
+                    )
+
+            self.job_controller = upload.ImageUploadJobController(
+                    self.log, self.loop, self
+                    )
+
+            self.task_creator = GlanceClientUploadTaskCreator(
+                    self.log, self.loop, self.cloud_accounts,
+                    self.glance_client, self
+                    )
+
+            self.rpc_handler = ImageDTSRPCHandler(
+                    self.log, self.loop, self.dts, self.cloud_accounts,
+                    self.glance_client, self.task_creator,
+                    self.job_controller, self
+                    )
+            yield from self.rpc_handler.register()
+
+            self.show_handler = ImageDTSShowHandler(
+                    self.log, self.loop, self.dts, self.job_controller, self
+                    )
+            yield from self.show_handler.register()
+        except Exception as e:
+            self.log.exception("Error during project {} register: e".
+                               format(self.name, e))
+
+    def deregister(self):
+        self.log.debug("De-register handlers for project: {}".format(self.name))
+        self.rpc_handler.deregister()
+        self.show_handler.deregister()
+        self.cloud_cfg_subscriber.deregister()
+
+    def on_cloud_account_create(self, account):
+        self.log.debug("adding cloud account: %s", account.name)
+        self.cloud_accounts[account.name] = account
+
+    def on_cloud_account_delete(self, account_name):
+        self.log.debug("deleting cloud account: %s", account_name)
+        if account_name not in self.cloud_accounts:
+            self.log.warning("cloud account not found: %s", account_name)
+        else:
+            del self.cloud_accounts[account_name]
+
 
 class ImageManagerTasklet(rift.tasklets.Tasklet):
     """
@@ -409,16 +527,13 @@
         super().__init__(*args, **kwargs)
         self.rwlog.set_category("rw-mano-log")
 
-        self.cloud_cfg_subscriber = None
         self.http_proxy = None
         self.proxy_server = None
         self.dts = None
-        self.job_controller = None
-        self.cloud_accounts = {}
         self.glance_client = None
-        self.task_creator = None
-        self.rpc_handler = None
-        self.show_handler = None
+        self.project_handler = None
+
+        self.projects = {}
 
     def start(self):
         super().start()
@@ -443,13 +558,6 @@
     @asyncio.coroutine
     def init(self):
         try:
-            self.log.debug("creating cloud account handler")
-            self.cloud_cfg_subscriber = CloudAccountDtsHandler(self.log, self.dts, self.log_hdl)
-            self.cloud_cfg_subscriber.register(
-                    self.on_cloud_account_create,
-                    self.on_cloud_account_delete
-                    )
-
             self.log.debug("creating http proxy server")
 
             self.http_proxy = glance_proxy_server.QuickProxyServer(self.log, self.loop)
@@ -459,43 +567,18 @@
                     )
             self.proxy_server.start()
 
-            self.job_controller = upload.ImageUploadJobController(
-                    self.log, self.loop
-                    )
-
             self.glance_client = glance_client.OpenstackGlanceClient.from_token(
                     self.log, "127.0.0.1", "9292", "test"
                     )
 
-            self.task_creator = GlanceClientUploadTaskCreator(
-                    self.log, self.loop, self.cloud_accounts, self.glance_client
-                    )
-
-            self.rpc_handler = ImageDTSRPCHandler(
-                    self.log, self.loop, self.dts, self.cloud_accounts, self.glance_client, self.task_creator,
-                    self.job_controller
-                    )
-            yield from self.rpc_handler.register()
-
-            self.show_handler = ImageDTSShowHandler(
-                    self.log, self.loop, self.dts, self.job_controller
-                    )
-            yield from self.show_handler.register()
+            self.log.debug("Creating project handler")
+            self.project_handler = ProjectHandler(self, ImageMgrProject,
+                                                  client=self.glance_client)
+            self.project_handler.register()
 
         except Exception as e:
             self.log.exception("error during init")
 
-    def on_cloud_account_create(self, account):
-        self.log.debug("adding cloud account: %s", account.name)
-        self.cloud_accounts[account.name] = account
-
-    def on_cloud_account_delete(self, account_name):
-        self.log.debug("deleting cloud account: %s", account_name)
-        if account_name not in self.cloud_accounts:
-            self.log.warning("cloud account not found: %s", account_name)
-
-        del self.cloud_accounts[account_name]
-
     @asyncio.coroutine
     def run(self):
         pass
diff --git a/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/upload.py b/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/upload.py
index 7ce74b2..3f1fb82 100644
--- a/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/upload.py
+++ b/rwlaunchpad/plugins/rwimagemgr/rift/tasklets/rwimagemgr/upload.py
@@ -51,9 +51,10 @@
     """ This class starts and manages ImageUploadJobs """
     MAX_COMPLETED_JOBS = 20
 
-    def __init__(self, log, loop, max_completed_jobs=MAX_COMPLETED_JOBS):
+    def __init__(self, log, loop, project, max_completed_jobs=MAX_COMPLETED_JOBS):
         self._log = log
         self._loop = loop
+        self._project = project
         self._job_id_gen = itertools.count(1)
         self._max_completed_jobs = max_completed_jobs
 
diff --git a/rwlaunchpad/plugins/rwimagemgr/test/utest_dts_handlers.py b/rwlaunchpad/plugins/rwimagemgr/test/utest_dts_handlers.py
index 7ba4f76..88205bd 100755
--- a/rwlaunchpad/plugins/rwimagemgr/test/utest_dts_handlers.py
+++ b/rwlaunchpad/plugins/rwimagemgr/test/utest_dts_handlers.py
@@ -138,7 +138,7 @@
                     )
 
             query_iter = yield from self.dts_c.query_read(
-                    "D,/rw-image-mgmt:upload-jobs",
+                    "D,/rw-project:project/rw-image-mgmt:upload-jobs",
                     )
 
             for fut_resp in query_iter:
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py
index 7571c57..2e8e3b2 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py
@@ -16,8 +16,10 @@
 #
 
 import json
+import logging
 import os
 import tempfile
+import yaml
 
 import gi
 gi.require_version('RwNsdYang', '1.0')
@@ -31,6 +33,8 @@
         RwYang,
         )
 
+from rift.mano.utils.project import NS_PROJECT
+
 
 class UnknownExtensionError(Exception):
     pass
@@ -97,7 +101,7 @@
 
     @property
     def yang_class(self):
-        """ The Protobuf's GI class (e.g. RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd) """
+        """ The Protobuf's GI class (e.g. RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd) """
         return self._yang_pb_cls
 
     @property
@@ -122,9 +126,16 @@
         return self.yang_class.from_json(self.model, decode(json), strict=False)
 
     def _from_yaml_file_hdl(self, file_hdl):
-        yaml = file_hdl.read()
+        yml = file_hdl.read()
 
-        return self.yang_class.from_yaml(self.model, decode(yaml), strict=False)
+        # Need to prefix project on to the descriptor and then
+        # convert to yang pb
+        # TODO: See if there is a better way to do this
+        desc = {NS_PROJECT: []}
+        desc[NS_PROJECT].append(yaml.load(decode(yml)))
+        # log = logging.getLogger('rw-mano-log')
+        # log.error("Desc from yaml: {}".format(desc))
+        return self.yang_class.from_yaml(self.model, yaml.dump(desc), strict=False)
 
     def to_json_string(self, pb_msg):
         """ Serialize a protobuf message into JSON
@@ -145,10 +156,15 @@
         try:
             json_str = pb_msg.to_json(self.model)
 
+            # Remove rw-project:project top level element
+            dic = json.loads(json_str)
+            jstr = json.dumps(dic[NS_PROJECT][0])
         except Exception as e:
             raise SerializationError(e)
 
-        return json_str
+        log = logging.getLogger('rw-mano-log')
+        log.error("Desc to json: {}".format(jstr))
+        return jstr
 
     def to_yaml_string(self, pb_msg):
         """ Serialize a protobuf message into YAML
@@ -262,22 +278,22 @@
 class VnfdSerializer(ProtoMessageSerializer):
     """ Creates a serializer for the VNFD descriptor"""
     def __init__(self):
-        super().__init__(VnfdYang, VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd)
+        super().__init__(VnfdYang, VnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd)
 
 
 class NsdSerializer(ProtoMessageSerializer):
     """ Creates a serializer for the NSD descriptor"""
     def __init__(self):
-        super().__init__(NsdYang, NsdYang.YangData_Nsd_NsdCatalog_Nsd)
+        super().__init__(NsdYang, NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd)
 
 
 class RwVnfdSerializer(ProtoMessageSerializer):
     """ Creates a serializer for the VNFD descriptor"""
     def __init__(self):
-        super().__init__(RwVnfdYang, RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd)
+        super().__init__(RwVnfdYang, RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd)
 
 
 class RwNsdSerializer(ProtoMessageSerializer):
     """ Creates a serializer for the NSD descriptor"""
     def __init__(self):
-        super().__init__(RwNsdYang, RwNsdYang.YangData_Nsd_NsdCatalog_Nsd)
+        super().__init__(RwNsdYang, RwNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd)
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/store.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/store.py
index 34fff1c..62b517a 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/store.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/store.py
@@ -52,9 +52,9 @@
     @property
     def root_dir(self):
         return self._root_dir
-    
 
     def _get_package_dir(self, package_id):
+        self._log.debug("Package dir {}, {}".format(self._root_dir, package_id))
         return os.path.join(self._root_dir, package_id)
 
     def _get_package_files(self, package_id):
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/datacenters.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/datacenters.py
index 05731a6..a481a11 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/datacenters.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/datacenters.py
@@ -35,19 +35,20 @@
 
     XPATH = "D,/rw-launchpad:datacenters"
 
-    def __init__(self, log, dts, loop):
+    def __init__(self, log, dts, loop, project):
         """Creates an instance of a DataCenterPublisher
 
         Arguments:
             tasklet - the tasklet that this publisher is registered for
 
         """
-        super().__init__(log, dts, loop)
+        super().__init__(log, dts, loop, project)
 
         self._ro_sub = mano_dts.ROAccountConfigSubscriber(
                         self.log,
                         self.dts,
                         self.loop,
+                        self.project,
                         callback=self.on_ro_account_change
                         )
         self.ro_accounts = {}
@@ -58,6 +59,15 @@
         elif action == RwDts.QueryAction.DELETE and ro_account.name in self.ro_accounts:
             del self.ro_accounts[ro_account.name]
 
+    def deregister(self):
+        self._log.debug("De-register datacenter handler for project {}".
+                        format(self.project.name))
+        if self.reg:
+            self.reg.deregister()
+            self.reg = None
+
+        self._ro_sub.deregister()
+
     @asyncio.coroutine
     def register(self):
         """Registers the publisher with DTS"""
@@ -105,7 +115,7 @@
 
                 xact_info.respond_xpath(
                         RwDts.XactRspCode.MORE,
-                        'D,/rw-launchpad:datacenters',
+                        self.project.add_project(DataCenterPublisher.XPATH),
                         datacenters,
                         )
 
@@ -119,7 +129,7 @@
 
         with self.dts.group_create() as group:
             self.reg = group.register(
-                    xpath=DataCenterPublisher.XPATH,
+                    xpath=self.project.add_project(DataCenterPublisher.XPATH),
                     handler=handler,
                     flags=RwDts.Flag.PUBLISHER,
                     )
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py
index 7fa6130..1e017b2 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py
@@ -195,21 +195,18 @@
 
 
 class ExportRpcHandler(mano_dts.AbstractRpcHandler):
-    def __init__(self, log, dts, loop, application, store_map, exporter, catalog_map):
+    def __init__(self, application, catalog_map):
         """
         Args:
             application: UploaderApplication
-            store_map: dict containing VnfdStore & NsdStore
-            exporter : DescriptorPackageArchiveExporter
             calalog_map: Dict containing Vnfds and Nsd onboarding.
         """
-        super().__init__(log, dts, loop)
+        super().__init__(application.log, application.dts, application.loop)
 
         self.application = application
-        self.store_map = store_map
-        self.exporter = exporter
+        self.store_map = application.package_store_map
+        self.exporter = application.exporter
         self.catalog_map = catalog_map
-        self.log = log
 
     @property
     def xpath(self):
@@ -240,7 +237,7 @@
 
         # Parse the IDs
         desc_id = msg.package_id
-        catalog = self.catalog_map[desc_type]
+        catalog = self.catalog_map[desc_type](project=msg.project_name)
 
         if desc_id not in catalog:
             raise ValueError("Unable to find package ID: {}".format(desc_id))
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/image.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/image.py
index b18e304..a025b37 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/image.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/image.py
@@ -65,9 +65,9 @@
         except Exception as e:
             raise ImageUploadError("Failed to upload image to catalog: %s" % str(e)) from e
 
-    def upload_image_to_cloud_accounts(self, image_name, image_checksum, cloud_accounts=None):
+    def upload_image_to_cloud_accounts(self, image_name, image_checksum, project, cloud_accounts=None):
         self._log.debug("uploading image %s to all cloud accounts", image_name)
-        upload_job = self._client.create_job_threadsafe(image_name, image_checksum, cloud_accounts)
+        upload_job = self._client.create_job_threadsafe(image_name, image_checksum, project, cloud_accounts)
         try:
             upload_job.wait_until_complete_threadsafe()
         except client.UploadJobError as e:
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/onboard.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/onboard.py
index b12e192..db7737f 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/onboard.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/onboard.py
@@ -17,6 +17,7 @@
 
 import requests
 
+from rift.mano.utils.project import DEFAULT_PROJECT
 from rift.package import convert
 from gi.repository import (
     NsdYang,
@@ -37,17 +38,17 @@
 class DescriptorOnboarder(object):
     """ This class is responsible for onboarding descriptors using Restconf"""
     DESC_ENDPOINT_MAP = {
-            NsdYang.YangData_Nsd_NsdCatalog_Nsd: "nsd-catalog/nsd",
-            RwNsdYang.YangData_Nsd_NsdCatalog_Nsd: "nsd-catalog/nsd",
-            VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd: "vnfd-catalog/vnfd",
-            RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd: "vnfd-catalog/vnfd",
+            NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd: "nsd-catalog/nsd",
+            RwNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd: "nsd-catalog/nsd",
+            VnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd: "vnfd-catalog/vnfd",
+            RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd: "vnfd-catalog/vnfd",
             }
 
     DESC_SERIALIZER_MAP = {
-            NsdYang.YangData_Nsd_NsdCatalog_Nsd: convert.NsdSerializer(),
-            RwNsdYang.YangData_Nsd_NsdCatalog_Nsd: convert.RwNsdSerializer(),
-            VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd: convert.VnfdSerializer(),
-            RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd: convert.RwVnfdSerializer(),
+            NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd: convert.NsdSerializer(),
+            RwNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd: convert.RwNsdSerializer(),
+            VnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd: convert.VnfdSerializer(),
+            RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd: convert.RwVnfdSerializer(),
             }
 
     HEADERS = {"content-type": "application/vnd.yang.data+json"}
@@ -72,28 +73,32 @@
 
         return headers
 
-    def _get_url(self, descriptor_msg):
+    def _get_url(self, descriptor_msg, project=None):
         if type(descriptor_msg) not in DescriptorOnboarder.DESC_SERIALIZER_MAP:
             raise TypeError("Invalid descriptor message type")
 
+        if project is None:
+            project = DEFAULT_PROJECT
+
         endpoint = DescriptorOnboarder.DESC_ENDPOINT_MAP[type(descriptor_msg)]
+        ep = "project/{}/{}".format(project, endpoint)
 
         url = "{}://{}:{}/api/config/{}".format(
                 "https" if self._use_ssl else "http",
                 self._host,
                 self.port,
-                endpoint,
+                ep,
                 )
 
         return url
 
-    def _make_request_args(self, descriptor_msg, auth=None):
+    def _make_request_args(self, descriptor_msg, auth=None, project=None):
         if type(descriptor_msg) not in DescriptorOnboarder.DESC_SERIALIZER_MAP:
             raise TypeError("Invalid descriptor message type")
 
         serializer = DescriptorOnboarder.DESC_SERIALIZER_MAP[type(descriptor_msg)]
         json_data = serializer.to_json_string(descriptor_msg)
-        url = self._get_url(descriptor_msg)
+        url = self._get_url(descriptor_msg, project=project)
 
         request_args = dict(
             url=url,
@@ -134,7 +139,7 @@
             self._log.error(msg)
             raise UpdateError(msg) from e
 
-    def onboard(self, descriptor_msg, auth=None):
+    def onboard(self, descriptor_msg, auth=None, project=None):
         """ Onboard the descriptor config
 
         Arguments:
@@ -145,20 +150,23 @@
             OnboardError - The descriptor config update failed
         """
 
-        request_args = self._make_request_args(descriptor_msg, auth)
+        request_args = self._make_request_args(descriptor_msg, auth, project)
         try:
             response = requests.post(**request_args)
             response.raise_for_status()
         except requests.exceptions.ConnectionError as e:
             msg = "Could not connect to restconf endpoint: %s" % str(e)
             self._log.error(msg)
+            self._log.exception(msg)
             raise OnboardError(msg) from e
         except requests.exceptions.HTTPError as e:
             msg = "POST request to %s error: %s" % (request_args["url"], response.text)
             self._log.error(msg)
+            self._log.exception(msg)
             raise OnboardError(msg) from e
         except requests.exceptions.Timeout as e:
             msg = "Timed out connecting to restconf endpoint: %s", str(e)
             self._log.error(msg)
+            self._log.exception(msg)
             raise OnboardError(msg) from e
 
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tasklet.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tasklet.py
index 0eff616..76dc781 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tasklet.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tasklet.py
@@ -40,6 +40,12 @@
 import rift.tasklets
 import rift.mano.cloud
 import rift.mano.config_agent
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+    get_add_delete_update_cfgs,
+    DEFAULT_PROJECT,
+    )
 from rift.package import store
 
 from . import uploader
@@ -53,45 +59,25 @@
 MAX_BODY_SIZE = 1 * MB  # Max. size loaded into memory!
 
 
-def get_add_delete_update_cfgs(dts_member_reg, xact, key_name):
-    # Unforunately, it is currently difficult to figure out what has exactly
-    # changed in this xact without Pbdelta support (RIFT-4916)
-    # As a workaround, we can fetch the pre and post xact elements and
-    # perform a comparison to figure out adds/deletes/updates
-    xact_cfgs = list(dts_member_reg.get_xact_elements(xact))
-    curr_cfgs = list(dts_member_reg.elements)
+class LaunchpadError(Exception):
+    pass
 
-    xact_key_map = {getattr(cfg, key_name): cfg for cfg in xact_cfgs}
-    curr_key_map = {getattr(cfg, key_name): cfg for cfg in curr_cfgs}
-
-    # Find Adds
-    added_keys = set(xact_key_map) - set(curr_key_map)
-    added_cfgs = [xact_key_map[key] for key in added_keys]
-
-    # Find Deletes
-    deleted_keys = set(curr_key_map) - set(xact_key_map)
-    deleted_cfgs = [curr_key_map[key] for key in deleted_keys]
-
-    # Find Updates
-    updated_keys = set(curr_key_map) & set(xact_key_map)
-    updated_cfgs = [xact_key_map[key] for key in updated_keys if xact_key_map[key] != curr_key_map[key]]
-
-    return added_cfgs, deleted_cfgs, updated_cfgs
-
+class LpProjectNotFound(Exception):
+    pass
 
 class CatalogDtsHandler(object):
-    def __init__(self, tasklet, app):
+    def __init__(self, project, app):
         self.app = app
         self.reg = None
-        self.tasklet = tasklet
+        self.project = project
 
     @property
     def log(self):
-        return self.tasklet.log
+        return self.project.log
 
     @property
     def dts(self):
-        return self.tasklet.dts
+        return self.project.dts
 
 
 class NsdCatalogDtsHandler(CatalogDtsHandler):
@@ -99,27 +85,27 @@
 
     def add_nsd(self, nsd):
         self.log.debug('nsd-catalog-handler:add:{}'.format(nsd.id))
-        if nsd.id not in self.tasklet.nsd_catalog:
-            self.tasklet.nsd_catalog[nsd.id] = nsd
+        if nsd.id not in self.project.nsd_catalog:
+            self.project.nsd_catalog[nsd.id] = nsd
         else:
             self.log.error("nsd already in catalog: {}".format(nsd.id))
 
     def update_nsd(self, nsd):
         self.log.debug('nsd-catalog-handler:update:{}'.format(nsd.id))
-        if nsd.id in self.tasklet.nsd_catalog:
-            self.tasklet.nsd_catalog[nsd.id] = nsd
+        if nsd.id in self.project.nsd_catalog:
+            self.project.nsd_catalog[nsd.id] = nsd
         else:
             self.log.error("unrecognized NSD: {}".format(nsd.id))
 
     def delete_nsd(self, nsd_id):
         self.log.debug('nsd-catalog-handler:delete:{}'.format(nsd_id))
-        if nsd_id in self.tasklet.nsd_catalog:
-            del self.tasklet.nsd_catalog[nsd_id]
+        if nsd_id in self.project.nsd_catalog:
+            del self.project.nsd_catalog[nsd_id]
         else:
             self.log.error("unrecognized NSD: {}".format(nsd_id))
 
         try:
-            self.tasklet.nsd_package_store.delete_package(nsd_id)
+            self.project.tasklet.nsd_package_store.delete_package(nsd_id)
         except store.PackageStoreError as e:
             self.log.warning("could not delete package from store: %s", str(e))
 
@@ -151,47 +137,54 @@
             for cfg in update_cfgs:
                 self.update_nsd(cfg)
 
-        self.log.debug("Registering for NSD catalog")
+        self.log.debug("Registering for NSD catalog in project".
+                       format(self.project.name))
 
         acg_handler = rift.tasklets.AppConfGroup.Handler(
                         on_apply=apply_config,
                         )
 
         with self.dts.appconf_group_create(acg_handler) as acg:
+            xpath = self.project.add_project(NsdCatalogDtsHandler.XPATH)
             self.reg = acg.register(
-                    xpath=NsdCatalogDtsHandler.XPATH,
+                    xpath=xpath,
                     flags=rwdts.Flag.SUBSCRIBER,
                     )
 
+    def deregister(self):
+        if self.reg:
+            self.reg.deregister()
+            self.reg = None
+
 
 class VnfdCatalogDtsHandler(CatalogDtsHandler):
     XPATH = "C,/vnfd:vnfd-catalog/vnfd:vnfd"
 
     def add_vnfd(self, vnfd):
         self.log.debug('vnfd-catalog-handler:add:{}'.format(vnfd.id))
-        if vnfd.id not in self.tasklet.vnfd_catalog:
-            self.tasklet.vnfd_catalog[vnfd.id] = vnfd
+        if vnfd.id not in self.project.vnfd_catalog:
+            self.project.vnfd_catalog[vnfd.id] = vnfd
 
         else:
             self.log.error("VNFD already in catalog: {}".format(vnfd.id))
 
     def update_vnfd(self, vnfd):
         self.log.debug('vnfd-catalog-handler:update:{}'.format(vnfd.id))
-        if vnfd.id in self.tasklet.vnfd_catalog:
-            self.tasklet.vnfd_catalog[vnfd.id] = vnfd
+        if vnfd.id in self.project.vnfd_catalog:
+            self.project.vnfd_catalog[vnfd.id] = vnfd
 
         else:
             self.log.error("unrecognized VNFD: {}".format(vnfd.id))
 
     def delete_vnfd(self, vnfd_id):
         self.log.debug('vnfd-catalog-handler:delete:{}'.format(vnfd_id))
-        if vnfd_id in self.tasklet.vnfd_catalog:
-            del self.tasklet.vnfd_catalog[vnfd_id]
+        if vnfd_id in self.project.vnfd_catalog:
+            del self.project.vnfd_catalog[vnfd_id]
         else:
             self.log.error("unrecognized VNFD: {}".format(vnfd_id))
 
         try:
-            self.tasklet.vnfd_package_store.delete_package(vnfd_id)
+            self.project.tasklet.vnfd_package_store.delete_package(vnfd_id)
         except store.PackageStoreError as e:
             self.log.warning("could not delete package from store: %s", str(e))
 
@@ -223,28 +216,36 @@
             for cfg in update_cfgs:
                 self.update_vnfd(cfg)
 
-        self.log.debug("Registering for VNFD catalog")
+        self.log.debug("Registering for VNFD catalog in project {}".
+                       format(self.project.name))
 
         acg_handler = rift.tasklets.AppConfGroup.Handler(
                         on_apply=apply_config,
                         )
 
         with self.dts.appconf_group_create(acg_handler) as acg:
+            xpath = self.project.add_project(VnfdCatalogDtsHandler.XPATH)
             self.reg = acg.register(
-                    xpath=VnfdCatalogDtsHandler.XPATH,
+                    xpath=xpath,
                     flags=rwdts.Flag.SUBSCRIBER,
                     )
 
+    def deregister(self):
+        if self.reg:
+            self.reg.deregister()
+            self.reg = None
+
 class CfgAgentAccountHandlers(object):
-    def __init__(self, dts, log, log_hdl, loop):
+    def __init__(self, dts, log, log_hdl, loop, project):
         self._dts = dts
         self._log = log
         self._log_hdl = log_hdl
         self._loop = loop
+        self._project = project
 
         self._log.debug("creating config agent account config handler")
         self.cfg_agent_cfg_handler = rift.mano.config_agent.ConfigAgentSubscriber(
-            self._dts, self._log,
+            self._dts, self._log, self._project,
             rift.mano.config_agent.ConfigAgentCallbacks(
                 on_add_apply=self.on_cfg_agent_account_added,
                 on_delete_apply=self.on_cfg_agent_account_deleted,
@@ -253,7 +254,7 @@
 
         self._log.debug("creating config agent account opdata handler")
         self.cfg_agent_operdata_handler = rift.mano.config_agent.CfgAgentDtsOperdataHandler(
-            self._dts, self._log, self._loop,
+            self._dts, self._log, self._loop, self._project
         )
 
     def on_cfg_agent_account_deleted(self, account):
@@ -269,38 +270,45 @@
         self.cfg_agent_cfg_handler.register()
         yield from self.cfg_agent_operdata_handler.register()
 
+    def deregister(self):
+        self.cfg_agent_operdata_handler.deregister()
+        self.cfg_agent_cfg_handler.deregister()
+
+
 class CloudAccountHandlers(object):
-    def __init__(self, dts, log, log_hdl, loop, app):
+    def __init__(self, dts, log, log_hdl, loop, app, project):
         self._log = log
         self._log_hdl = log_hdl
         self._dts = dts
         self._loop = loop
         self._app = app
+        self._project = project
 
-        self._log.debug("creating cloud account config handler")
+        self._log.debug("Creating cloud account config handler for project {}".
+                        format(project.name))
         self.cloud_cfg_handler = rift.mano.cloud.CloudAccountConfigSubscriber(
-            self._dts, self._log, self._log_hdl,
+            self._dts, self._log, self._log_hdl, self._project,
             rift.mano.cloud.CloudAccountConfigCallbacks(
                 on_add_apply=self.on_cloud_account_added,
                 on_delete_apply=self.on_cloud_account_deleted,
-            )
+            ),
         )
 
         self._log.debug("creating cloud account opdata handler")
         self.cloud_operdata_handler = rift.mano.cloud.CloudAccountDtsOperdataHandler(
-            self._dts, self._log, self._loop,
+            self._dts, self._log, self._loop, self._project,
         )
 
     def on_cloud_account_deleted(self, account_name):
         self._log.debug("cloud account deleted")
-        self._app.accounts.clear()
-        self._app.accounts.extend(list(self.cloud_cfg_handler.accounts.values()))
+        self._app.accounts[self._project.name] = \
+            list(self.cloud_cfg_handler.accounts.values())
         self.cloud_operdata_handler.delete_cloud_account(account_name)
 
     def on_cloud_account_added(self, account):
         self._log.debug("cloud account added")
-        self._app.accounts.clear()
-        self._app.accounts.extend(list(self.cloud_cfg_handler.accounts.values()))
+        self._app.accounts[self._project.name] = \
+            list(self.cloud_cfg_handler.accounts.values())
         self._log.debug("accounts: %s", self._app.accounts)
         self.cloud_operdata_handler.add_cloud_account(account)
 
@@ -309,6 +317,85 @@
         self.cloud_cfg_handler.register()
         yield from self.cloud_operdata_handler.register()
 
+    def deregister(self):
+        self.cloud_cfg_handler.deregister()
+        yield from self.cloud_operdata_handler.deregister()
+
+
+class LaunchpadProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(LaunchpadProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+        self._app = kw['app']
+
+        self.config_handler = None
+        self.nsd_catalog_handler = None
+        self.vld_catalog_handler = None
+        self.vnfd_catalog_handler = None
+        self.cloud_handler = None
+        self.datacenter_handler = None
+        self.lp_config_handler = None
+        self.account_handler = None
+
+        self.nsd_catalog = dict()
+        self.vld_catalog = dict()
+        self.vnfd_catalog = dict()
+
+    @property
+    def dts(self):
+        return self._dts
+
+    @property
+    def loop(self):
+        return self._loop
+
+    @asyncio.coroutine
+    def register(self):
+        self.log.debug("creating NSD catalog handler for project {}".format(self.name))
+        self.nsd_catalog_handler = NsdCatalogDtsHandler(self, self._app)
+        yield from self.nsd_catalog_handler.register()
+
+        self.log.debug("creating VNFD catalog handler for project {}".format(self.name))
+        self.vnfd_catalog_handler = VnfdCatalogDtsHandler(self, self._app)
+        yield from self.vnfd_catalog_handler.register()
+
+        self.log.debug("creating datacenter handler for project {}".format(self.name))
+        self.datacenter_handler = datacenters.DataCenterPublisher(self.log, self.dts,
+                                                                  self.loop, self)
+        yield from self.datacenter_handler.register()
+
+        self.log.debug("creating cloud account handler for project {}".format(self.name))
+        self.cloud_handler = CloudAccountHandlers(self.dts, self.log, self.log_hdl,
+                                                  self.loop, self._app, self)
+        yield from self.cloud_handler.register()
+
+        self.log.debug("creating config agent handler for project {}".format(self.name))
+        self.config_handler = CfgAgentAccountHandlers(self.dts, self.log, self.log_hdl,
+                                                      self.loop, self)
+        yield from self.config_handler.register()
+
+    def deregister(self):
+        self.log.debug("De-register handlers for project: {}".format(self.name))
+        self.config_handler.deregister()
+        self.cloud_handler.deregister()
+        self.datacenter_handler.deregister()
+        self.vnfd_catalog_handler.deregister()
+        self.nsd_catalog_handler.deregister()
+
+    @asyncio.coroutine
+    def delete_prepare(self):
+        if self.nsd_catalog or self.vnfd_catalog or self.vld_catalog:
+            return False
+        return True
+
+    @property
+    def cloud_accounts(self):
+        if self.cloud_handler is None:
+            return list()
+
+        return list(self.cloud_handler.cloud_cfg_handler.accounts.values())
+
 
 class LaunchpadTasklet(rift.tasklets.Tasklet):
     UPLOAD_MAX_BODY_SIZE = MAX_BODY_SIZE
@@ -320,31 +407,36 @@
         self.rwlog.set_category("rw-mano-log")
         self.rwlog.set_subcategory("launchpad")
 
-        self.app = None
-        self.server = None
-
-        self.account_handler = None
-        self.config_handler = None
-        self.nsd_catalog_handler = None
-        self.vld_catalog_handler = None
-        self.vnfd_catalog_handler = None
-        self.cloud_handler = None
-        self.datacenter_handler = None
-        self.lp_config_handler = None
+        self.dts = None
+        self.project_handler = None
 
         self.vnfd_package_store = store.VnfdPackageFilesystemStore(self.log)
         self.nsd_package_store = store.NsdPackageFilesystemStore(self.log)
 
-        self.nsd_catalog = dict()
-        self.vld_catalog = dict()
-        self.vnfd_catalog = dict()
+        self.app = None
+        self.server = None
+        self.projects = {}
+        print("LP Tasklet init")
 
-    @property
-    def cloud_accounts(self):
-        if self.cloud_handler is None:
-            return list()
+    def _get_project(project=None):
+        if project is None:
+            project = DEFAULT_PROJECT
 
-        return list(self.cloud_handler.cloud_cfg_handler.accounts.values())
+        if project in self.projects:
+            return self.projects[project]
+
+        msg = "Project {} not found".format(project)
+        self._log.error(msg)
+        raise LpProjectNotFound(msg)
+
+    def nsd_catalog_get(self, project=None):
+        return self._get_project(project=project).nsd_catalog
+
+    def vnfd_catalog_get(self, project=None):
+        return self._get_project(project=project).vnfd_catalog
+
+    def get_cloud_accounts(self, project=None):
+        return self._get_project(project=project).cloud_accounts
 
     def start(self):
         super(LaunchpadTasklet, self).start()
@@ -368,56 +460,51 @@
             self.log.exception("Caught Exception in LP stop")
             raise
 
+    def get_vnfd_catalog(self, project):
+        return self.projects[project].vnfd_catalog
+
+    def get_nsd_catalog(self, project):
+        return self.projects[project].nsd_catalog
+
     @asyncio.coroutine
     def init(self):
-        io_loop = rift.tasklets.tornado.TaskletAsyncIOLoop(asyncio_loop=self.loop)
-        self.app = uploader.UploaderApplication.from_tasklet(self)
-        yield from self.app.register()
+        try:
+            io_loop = rift.tasklets.tornado.TaskletAsyncIOLoop(asyncio_loop=self.loop)
+            self.app = uploader.UploaderApplication.from_tasklet(self)
+            yield from self.app.register()
 
-        manifest = self.tasklet_info.get_pb_manifest()
-        ssl_cert = manifest.bootstrap_phase.rwsecurity.cert
-        ssl_key = manifest.bootstrap_phase.rwsecurity.key
-        ssl_options = {
+            manifest = self.tasklet_info.get_pb_manifest()
+            ssl_cert = manifest.bootstrap_phase.rwsecurity.cert
+            ssl_key = manifest.bootstrap_phase.rwsecurity.key
+            ssl_options = {
                 "certfile": ssl_cert,
                 "keyfile": ssl_key,
-                }
+            }
 
-        if manifest.bootstrap_phase.rwsecurity.use_ssl:
-            self.server = tornado.httpserver.HTTPServer(
-                self.app,
-                max_body_size=LaunchpadTasklet.UPLOAD_MAX_BODY_SIZE,
-                io_loop=io_loop,
-                ssl_options=ssl_options,
-            )
-
-        else:
-            self.server = tornado.httpserver.HTTPServer(
-                self.app,
-                max_body_size=LaunchpadTasklet.UPLOAD_MAX_BODY_SIZE,
-                io_loop=io_loop,
-            )
-
-        self.log.debug("creating NSD catalog handler")
-        self.nsd_catalog_handler = NsdCatalogDtsHandler(self, self.app)
-        yield from self.nsd_catalog_handler.register()
-
-        self.log.debug("creating VNFD catalog handler")
-        self.vnfd_catalog_handler = VnfdCatalogDtsHandler(self, self.app)
-        yield from self.vnfd_catalog_handler.register()
-
-        self.log.debug("creating datacenter handler")
-        self.datacenter_handler = datacenters.DataCenterPublisher(self.log, self.dts, self.loop)
-        yield from self.datacenter_handler.register()
-
-        self.log.debug("creating cloud account handler")
-        self.cloud_handler = CloudAccountHandlers(
-                self.dts, self.log, self.log_hdl, self.loop, self.app
+            if manifest.bootstrap_phase.rwsecurity.use_ssl:
+                self.server = tornado.httpserver.HTTPServer(
+                    self.app,
+                    max_body_size=LaunchpadTasklet.UPLOAD_MAX_BODY_SIZE,
+                    io_loop=io_loop,
+                    ssl_options=ssl_options,
                 )
-        yield from self.cloud_handler.register()
 
-        self.log.debug("creating config agent handler")
-        self.config_handler = CfgAgentAccountHandlers(self.dts, self.log, self.log_hdl, self.loop)
-        yield from self.config_handler.register()
+            else:
+                self.server = tornado.httpserver.HTTPServer(
+                    self.app,
+                    max_body_size=LaunchpadTasklet.UPLOAD_MAX_BODY_SIZE,
+                    io_loop=io_loop,
+                )
+
+            self.log.debug("Registering project handler")
+            print("PJ: Registering project handler")
+            self.project_handler = ProjectHandler(self, LaunchpadProject,
+                                                  app=self.app)
+            self.project_handler.register()
+
+        except Exception as e:
+            self.log.error("Exception : {}".format(e))
+            self.log.exception(e)
 
     @asyncio.coroutine
     def run(self):
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/uploader.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/uploader.py
index c908bb3..1406a89 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/uploader.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/uploader.py
@@ -146,12 +146,12 @@
 
 
 class UploadRpcHandler(mano_dts.AbstractRpcHandler):
-    def __init__(self, log, dts, loop, application):
+    def __init__(self, application):
         """
         Args:
             application: UploaderApplication
         """
-        super().__init__(log, dts, loop)
+        super().__init__(application.log, application.dts, application.loop)
         self.application = application
 
     @property
@@ -164,30 +164,41 @@
         log = self.application.get_logger(transaction_id)
         log.message(OnboardStart())
 
+        self.log.debug("Package create RPC: {}".format(msg))
 
         auth = None
         if msg.username is not None:
             auth = (msg.username, msg.password)
 
+        try:
+            project = msg.project_name
+        except AttributeError as e:
+            self._log.warning("Did not get project name in RPC: {}".
+                              format(msg.as_dict()))
+            project = rift.mano.utils.project.DEFAULT_PROJECT
+
         self.application.onboard(
                 msg.external_url,
                 transaction_id,
-                auth=auth
+                auth=auth,
+                project=project,
                 )
 
         rpc_op = RPC_PACKAGE_CREATE_ENDPOINT.from_dict({
-                "transaction_id": transaction_id})
+            "transaction_id": transaction_id,
+            "project_name": project,
+        })
 
         return rpc_op
 
 
 class UpdateRpcHandler(mano_dts.AbstractRpcHandler):
-    def __init__(self, log, dts, loop, application):
+    def __init__(self, application):
         """
         Args:
             application: UploaderApplication
         """
-        super().__init__(log, dts, loop)
+        super().__init__(application.log, application.dts, application.loop)
         self.application = application
 
     @property
@@ -208,11 +219,14 @@
         self.application.update(
                 msg.external_url,
                 transaction_id,
-                auth=auth
+                auth=auth,
+                project=msg.project_name,
                 )
 
         rpc_op = RPC_PACKAGE_UPDATE_ENDPOINT.from_dict({
-                "transaction_id": transaction_id})
+            "transaction_id": transaction_id,
+            "project_name": msg.project_name,
+        })
 
         return rpc_op
 
@@ -231,11 +245,12 @@
 
 class UpdatePackage(downloader.DownloaderProtocol):
 
-    def __init__(self, log, loop, url, auth,
+    def __init__(self, log, loop, project, url, auth,
                  onboarder, uploader, package_store_map):
         super().__init__()
         self.log = log
         self.loop = loop
+        self.project = project
         self.url = url
         self.auth = auth
         self.onboarder = onboarder
@@ -355,7 +370,7 @@
                             )
                 try:
                     self.uploader.upload_image(image_name, image_checksum, image_hdl)
-                    self.uploader.upload_image_to_cloud_accounts(image_name, image_checksum)
+                    self.uploader.upload_image_to_cloud_accounts(image_name, image_checksum, self.project)
 
                 except image.ImageUploadError as e:
                     self.log.exception("Failed to upload image: %s", image_name)
@@ -427,22 +442,24 @@
         self.log.message(UpdateDescriptorUpdate())
 
         try:
-            self.onboarder.update(descriptor_msg)
+            self.onboarder.update(descriptor_msg, project=self.project)
         except onboard.UpdateError as e:
             raise MessageException(UpdateDescriptorError(package.descriptor_file)) from e
 
 
 class OnboardPackage(downloader.DownloaderProtocol):
 
-    def __init__(self, log, loop, url, auth,
+    def __init__(self, log, loop, project, url, auth,
                  onboarder, uploader, package_store_map):
         self.log = log
         self.loop = loop
+        self.project = project
         self.url = url
         self.auth = auth
         self.onboarder = onboarder
         self.uploader = uploader
         self.package_store_map = package_store_map
+        self.project = project
 
     def _onboard_package(self, packages):
         # Extract package could return multiple packages if
@@ -623,7 +640,7 @@
         self.log.message(OnboardDescriptorOnboard())
 
         try:
-            self.onboarder.onboard(descriptor_msg)
+            self.onboarder.onboard(descriptor_msg, project=self.project)
         except onboard.OnboardError as e:
             raise MessageException(OnboardDescriptorError(package.descriptor_file)) from e
 
@@ -637,29 +654,23 @@
         ssl_cert = manifest.bootstrap_phase.rwsecurity.cert
         ssl_key = manifest.bootstrap_phase.rwsecurity.key
         return cls(
-                tasklet.log,
-                tasklet.dts,
-                tasklet.loop,
-                ssl=(ssl_cert, ssl_key),
-                vnfd_store=tasklet.vnfd_package_store,
-                nsd_store=tasklet.nsd_package_store,
-                vnfd_catalog=tasklet.vnfd_catalog,
-                nsd_catalog=tasklet.nsd_catalog)
+            tasklet,
+            ssl=(ssl_cert, ssl_key),
+            vnfd_store=tasklet.vnfd_package_store,
+            nsd_store=tasklet.nsd_package_store)
 
     def __init__(
             self,
-            log,
-            dts,
-            loop,
+            tasklet,
             ssl=None,
             vnfd_store=None,
-            nsd_store=None,
-            vnfd_catalog=None,
-            nsd_catalog=None):
+            nsd_store=None):
 
-        self.log = log
-        self.loop = loop
-        self.dts = dts
+        self.log = tasklet.log
+        self.loop = tasklet.loop
+        self.dts = tasklet.dts
+
+        self.accounts = {}
 
         self.use_ssl = False
         self.ssl_cert, self.ssl_key = None, None
@@ -673,7 +684,6 @@
         if not nsd_store:
             nsd_store = rift.package.store.NsdPackageFilesystemStore(self.log)
 
-        self.accounts = []
         self.messages = collections.defaultdict(list)
         self.export_dir = os.path.join(os.environ['RIFT_ARTIFACTS'], 'launchpad/exports')
 
@@ -689,24 +699,16 @@
         self.exporter = export.DescriptorPackageArchiveExporter(self.log)
         self.loop.create_task(export.periodic_export_cleanup(self.log, self.loop, self.export_dir))
 
-        self.vnfd_catalog = vnfd_catalog
-        self.nsd_catalog = nsd_catalog
+        self.get_vnfd_catalog = tasklet.get_vnfd_catalog
+        self.get_nsd_catalog = tasklet.get_nsd_catalog
         catalog_map = {
-                 "vnfd": self.vnfd_catalog,
-                 "nsd": self.nsd_catalog
+                 "vnfd": self.get_vnfd_catalog,
+                 "nsd": self.get_nsd_catalog
                  }
 
-        self.upload_handler = UploadRpcHandler(self.log, self.dts, self.loop, self)
-        self.update_handler = UpdateRpcHandler(self.log, self.dts, self.loop, self)
-        self.export_handler = export.ExportRpcHandler(
-                    self.log,
-                    self.dts,
-                    self.loop,
-                    self,
-                    store_map=self.package_store_map,
-                    exporter=self.exporter,
-                    catalog_map=catalog_map
-                    )
+        self.upload_handler = UploadRpcHandler(self)
+        self.update_handler = UpdateRpcHandler(self)
+        self.export_handler = export.ExportRpcHandler(self, catalog_map)
 
         attrs = dict(log=self.log, loop=self.loop)
 
@@ -737,12 +739,13 @@
     def get_logger(self, transaction_id):
         return message.Logger(self.log, self.messages[transaction_id])
 
-    def onboard(self, url, transaction_id, auth=None):
+    def onboard(self, url, transaction_id, auth=None, project=None):
         log = message.Logger(self.log, self.messages[transaction_id])
 
         onboard_package = OnboardPackage(
                 log,
                 self.loop,
+                project,
                 url,
                 auth,
                 self.onboarder,
@@ -752,12 +755,13 @@
 
         self.loop.run_in_executor(None, onboard_package.download_package)
 
-    def update(self, url, transaction_id, auth=None):
+    def update(self, url, transaction_id, auth=None, project=None):
         log = message.Logger(self.log, self.messages[transaction_id])
 
         update_package = UpdatePackage(
                 log,
                 self.loop,
+                project,
                 url,
                 auth,
                 self.onboarder,
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/scripts/onboard_pkg b/rwlaunchpad/plugins/rwlaunchpadtasklet/scripts/onboard_pkg
index 2b2eb91..d5bb4e5 100755
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/scripts/onboard_pkg
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/scripts/onboard_pkg
@@ -100,6 +100,8 @@
         self._log = log
         self._args = args
 
+        self._project = args.project
+
         self._pkgs = None
 
         self._service_name = None
@@ -121,30 +123,36 @@
                                     user=self._user,
                                     passwd=self._password,
                                     api_server_ip=self._api_server_ip)
+
         self._upload_url = "curl -k https://{ip}:{port}/api/upload". \
                             format(ip=self._ip,
                                    port=self._uport)
 
         self._headers = '-H "accept: application/json"' + \
                         ' -H "content-type: application/json"'
-        self._conf_url = "curl -k {header} --user \"{user}:{passwd}\" https://{ip}:{port}/api/config". \
+
+        self._conf_url = "curl -k {header} --user \"{user}:{passwd}\" https://{ip}:{port}/api/config/project/{project}". \
                        format(header=self._headers,
                               user=self._user,
                               passwd=self._password,
                               ip=self._ip,
-                              port=self._rport)
-        self._oper_url = "curl -k {header} --user \"{user}:{passwd}\" https://{ip}:{port}/api/operational". \
+                              port=self._rport,
+                              project=self._project)
+
+        self._oper_url = "curl -k {header} --user \"{user}:{passwd}\" https://{ip}:{port}/api/operational/project/{project}". \
                        format(header=self._headers,
                               user=self._user,
                               passwd=self._password,
                               ip=self._ip,
-                              port=self._rport)
+                              port=self._rport,
+                              project=self._project)
 
     @property
     def log(self):
         return self._log
 
     def validate_args(self):
+        args = self._args
         if args.upload_pkg is not None:
             self._pkgs = args.upload_pkg
             self.log.debug("Packages to upload: {}".format(self._pkgs))
@@ -165,8 +173,8 @@
                     uuid.UUID(args.datacenter)
                     self._dc = args.datacenter
                 except ValueError as e:
-                    raise OnboardPkgInvalidDescId("Invalid UUID for datacenter: {}".
-                                                  format(args.datacenter))
+                    raise OnboardPkgInvalidDescId("Invalid UUID for datacenter {}: {}".
+                                                  format(args.datacenter, e))
 
             elif args.vim_account:
                 self._account = args.vim_account
@@ -181,8 +189,8 @@
                                                                    self._service_name,
                                                                    self._account))
 
-        if (self._pkgs is None) and (self._nsd_id is None):
-            raise OnboardPkgInputError("Need to specify either upload-pkg or instantiate options")
+        if (self._pkgs is None) and (self._nsd_id is None) and (not args.list_nsds):
+            raise OnboardPkgInputError("Need to specify either upload-pkg or instantiate or list options")
 
         # Validate the port numbers are correct
         def valid_port(port):
@@ -334,7 +342,12 @@
                                      format(self._nsd_id,
                                             js['error']))
 
-        nsd = js['nsd:nsd']
+        try:
+            nsd = js['nsd:nsd']
+        except KeyError as e:
+            raise OnboardPkgNsdError("NSD ID {} provided is not valid".
+                                     format(self._nsd_id))
+
         self.log.debug("NSD to instantiate: {}".format(nsd))
 
         # Generate a UUID for NS
@@ -381,11 +394,41 @@
         self.log.info("Successfully initiated instantiation of NS as {} ({})".
                       format(self._service_name, ns_id))
 
+    def list_nsds(self):
+        if self._args.list_nsds:
+            self.log.debug("Check NSDS at {}:{}, with credentials {}:{}".
+                           format(self._ip, self._rport, self._user, self._password))
+
+            rest_url = self._conf_url+"/nsd-catalog/nsd"
+            try:
+                output = self._exec_cmd(rest_url)
+                self.log.debug("Output of NSD list: {}".
+                               format(output))
+                if output:
+                    js = json.loads(output)
+                    if "error" in js:
+                        raise OnboardPkgRcConnError("SO Restconf connect error: {}".
+                                                    format(js["error"]))
+                else:
+                    print("No NSDs found on SO")
+                    return
+
+                self.log.debug("NSD list: {}".format(js))
+                print('List of NSDs on SO:\nName\tID')
+                for nsd in js['nsd:nsd']:
+                    print('{}\t{}'.format(nsd['name'], nsd['id']))
+
+            except OnboardPkgCmdError as e:
+                self.log.error("SO restconf connect failed: {}".format(e))
+                raise OnboardPkgRcConnError("SO Restconf connect error: {}".
+                                            format(e))
+
     def process(self):
         self.validate_args()
         self.validate_connectivity()
         self.upload_packages()
         self.instantiate()
+        self.list_nsds()
 
 
 if __name__ == "__main__":
@@ -397,6 +440,9 @@
                         help="Descriptor packages to upload. " + \
                         "If multiple descriptors are provided, they are uploaded in the same sequence.")
 
+    parser.add_argument("-l", "--list-nsds", action='store_true',
+                        help="List available network service descriptors")
+
     parser.add_argument("-i", "--instantiate",
                         help="Instantiate a network service with the name")
     parser.add_argument("-d", "--nsd-id",
@@ -406,6 +452,8 @@
     parser.add_argument("-c", "--vim-account",
                         help="Cloud/VIM account to instantiate on")
 
+    parser.add_argument("--project", default='default',
+                        help="Project to use, default 'default'")
     parser.add_argument("-o", "--onboard-port", default=8443, type=int,
                         help="Onboarding port number - node port number, default 8443")
     parser.add_argument("-p", "--upload-port", default=4567, type=int,
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_export.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_export.py
index 7a787c7..522c1a8 100755
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_export.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_export.py
@@ -59,7 +59,7 @@
         self._vnfd_serializer = rift.package.convert.VnfdSerializer()
 
     def test_create_archive(self):
-        rw_vnfd_msg = RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd(
+        rw_vnfd_msg = RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd(
                 id="new_id", name="new_name", description="new_description"
                 )
         json_desc_str = self._rw_vnfd_serializer.to_json_string(rw_vnfd_msg)
@@ -80,11 +80,11 @@
             self.assertEqual(package.descriptor_msg, rw_vnfd_msg)
 
     def test_export_package(self):
-        rw_vnfd_msg = RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd(
+        rw_vnfd_msg = RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd(
                 id="new_id", name="new_name", description="new_description",
                 meta="THIS FIELD IS NOT IN REGULAR VNFD"
                 )
-        vnfd_msg = VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd()
+        vnfd_msg = VnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd()
         vnfd_msg.from_dict(rw_vnfd_msg.as_dict(), ignore_missing_keys=True)
 
         self.assertNotEqual(rw_vnfd_msg, vnfd_msg)
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_onboard.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_onboard.py
index 871132f..b3a7458 100755
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_onboard.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_onboard.py
@@ -218,7 +218,7 @@
 
     @rift.test.dts.async_test
     def test_onboard_nsd(self):
-        nsd_msg = NsdYang.YangData_Nsd_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
+        nsd_msg = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
         yield from self._loop.run_in_executor(None, self._onboarder.onboard, nsd_msg)
         self.assertEqual(self._handler_info.last_request_message, nsd_msg)
         self.assertEqual(self._handler_info.last_descriptor_type, "nsd")
@@ -226,7 +226,7 @@
 
     @rift.test.dts.async_test
     def test_update_nsd(self):
-        nsd_msg = NsdYang.YangData_Nsd_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
+        nsd_msg = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
         yield from self._loop.run_in_executor(None, self._onboarder.update, nsd_msg)
         self.assertEqual(self._handler_info.last_request_message, nsd_msg)
         self.assertEqual(self._handler_info.last_descriptor_type, "nsd")
@@ -234,7 +234,7 @@
 
     @rift.test.dts.async_test
     def test_bad_descriptor_type(self):
-        nsd_msg = NsdYang.YangData_Nsd_NsdCatalog()
+        nsd_msg = NsdYang.YangData_RwProject_Project_NsdCatalog()
         with self.assertRaises(TypeError):
             yield from self._loop.run_in_executor(None, self._onboarder.update, nsd_msg)
 
@@ -246,7 +246,7 @@
         # Use a port not used by the instantiated server
         new_port = self._port - 1
         self._onboarder.port = new_port
-        nsd_msg = NsdYang.YangData_Nsd_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
+        nsd_msg = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
 
         with self.assertRaises(onboard.OnboardError):
             yield from self._loop.run_in_executor(None, self._onboarder.onboard, nsd_msg)
@@ -259,7 +259,7 @@
         # Set the timeout to something minimal to speed up test
         self._onboarder.timeout = .1
 
-        nsd_msg = NsdYang.YangData_Nsd_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
+        nsd_msg = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd(id=str(uuid.uuid4()), name="nsd_name")
 
         # Force the request to timeout by running the call synchronously so the
         with self.assertRaises(onboard.OnboardError):
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_uploader_app_dts.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_uploader_app_dts.py
index fdc2e22..18b53d5 100755
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_uploader_app_dts.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/test/utest_uploader_app_dts.py
@@ -74,7 +74,7 @@
         mock_vnfd_catalog = mock.MagicMock()
         self.uid, path = self.create_mock_package()
 
-        mock_vnfd = RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd.from_dict({
+        mock_vnfd = RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd.from_dict({
               "id": self.uid
             })
         mock_vnfd_catalog = {self.uid: mock_vnfd}
diff --git a/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/core.py b/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/core.py
index b8abea7..f43da6f 100644
--- a/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/core.py
+++ b/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/core.py
@@ -231,7 +231,7 @@
         self._account = account
         self._plugin = plugin
         self._timestamp = 0
-        self._metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
+        self._metrics = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
         self._vdur = vdur
         self._vim_id = vdur.vim_id
         self._updating = None
@@ -305,7 +305,7 @@
 
             try:
                 # Create uninitialized metric structure
-                vdu_metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
+                vdu_metrics = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
 
                 # VCPU
                 vdu_metrics.vcpu.total = self.vdur.vm_flavor.vcpu_count
@@ -549,17 +549,19 @@
     different sub-systems that are used to monitor the NFVI.
     """
 
-    def __init__(self, loop, log, config):
+    def __init__(self, loop, log, config, project):
         """Create a Monitor object
 
         Arguments:
-            loop   - an event loop
-            log    - the logger used by this object
-            config - an instance of InstanceConfiguration
+            loop    - an event loop
+            log     - the logger used by this object
+            config  - an instance of InstanceConfiguration
+            project - an instance of the project
 
         """
         self._loop = loop
         self._log = log
+        self._project = project
 
         self._cloud_accounts = dict()
         self._nfvi_plugins = NfviMetricsPluginManager(log)
@@ -581,6 +583,10 @@
         return self._log
 
     @property
+    def project(self):
+        return self._project
+
+    @property
     def cache(self):
         """The NFVI metrics cache"""
         return self._cache
diff --git a/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/tasklet.py b/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/tasklet.py
index 4ab351e..b9173e6 100644
--- a/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/tasklet.py
+++ b/rwlaunchpad/plugins/rwmonitor/rift/tasklets/rwmonitor/tasklet.py
@@ -90,30 +90,34 @@
 
 import rift.tasklets
 import rift.mano.cloud
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+    )
 
 from . import core
 
 
 class DtsHandler(object):
-    def __init__(self, tasklet):
+    def __init__(self, project):
         self.reg = None
-        self.tasklet = tasklet
+        self.project = project
 
     @property
     def log(self):
-        return self.tasklet.log
+        return self.project._log
 
     @property
     def log_hdl(self):
-        return self.tasklet.log_hdl
+        return self.project._log_hdl
 
     @property
     def dts(self):
-        return self.tasklet.dts
+        return self.project._dts
 
     @property
     def loop(self):
-        return self.tasklet.loop
+        return self.project._loop
 
     @property
     def classname(self):
@@ -151,7 +155,7 @@
 
         with self.dts.group_create() as group:
             group.register(
-                    xpath=VnfrCatalogSubscriber.XPATH,
+                    xpath=self.project.add_project(VnfrCatalogSubscriber.XPATH),
                     flags=rwdts.Flag.SUBSCRIBER,
                     handler=handler,
                     )
@@ -173,20 +177,20 @@
 
         with self.dts.appconf_group_create(acg_handler) as acg:
             self.reg = acg.register(
-                    xpath=NsInstanceConfigSubscriber.XPATH,
+                    xpath=self.project.add_project(NsInstanceConfigSubscriber.XPATH),
                     flags=rwdts.Flag.SUBSCRIBER,
                     )
 
 
 class CloudAccountDtsHandler(DtsHandler):
-    def __init__(self, tasklet):
-        super().__init__(tasklet)
+    def __init__(self, project):
+        super().__init__(project)
         self._cloud_cfg_subscriber = None
 
     def register(self):
         self.log.debug("creating cloud account config handler")
         self._cloud_cfg_subscriber = rift.mano.cloud.CloudAccountConfigSubscriber(
-               self.dts, self.log, self.log_hdl,
+               self.dts, self.log, self.log_hdl, self.project,
                rift.mano.cloud.CloudAccountConfigCallbacks(
                    on_add_apply=self.tasklet.on_cloud_account_create,
                    on_delete_apply=self.tasklet.on_cloud_account_delete,
@@ -208,7 +212,7 @@
     # before timing out, the current data will be published instead.
     TIMEOUT = 2.0
 
-    def __init__(self, tasklet, vnfr, vdur):
+    def __init__(self, project, vnfr, vdur):
         """Create an instance of VdurNvfiPublisher
 
         Arguments:
@@ -217,12 +221,12 @@
             vdur    - the VDUR of the VDU whose metrics are published
 
         """
-        super().__init__(tasklet)
+        super().__init__(project)
         self._vnfr = vnfr
         self._vdur = vdur
 
         self._handle = None
-        self._xpath = VdurNfviMetricsPublisher.XPATH.format(vnfr.id, vdur.id)
+        self._xpath = project.add_project(VdurNfviMetricsPublisher.XPATH.format(vnfr.id, vdur.id))
 
         self._deregistered = asyncio.Event(loop=self.loop)
 
@@ -321,7 +325,7 @@
 
             with self.dts.appconf_group_create(acg_handler) as acg:
                 self.reg = acg.register(
-                        xpath="C,/rw-launchpad:launchpad-config",
+                        xpath=self.project.add_project("C,/rw-launchpad:launchpad-config"),
                         flags=rwdts.Flag.SUBSCRIBER,
                         )
 
@@ -335,8 +339,8 @@
     them on to the tasklet.
     """
 
-    def __init__(self, tasklet):
-        super().__init__(tasklet)
+    def __init__(self, project):
+        super().__init__(project)
         self._handle = None
 
     @asyncio.coroutine
@@ -345,6 +349,10 @@
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
             try:
+
+                if not self.project.rpc_check(msg, xact_info=xact_info):
+                    return
+
                 response = VnfrYang.YangOutput_Vnfr_CreateAlarm()
                 response.alarm_id = yield from self.tasklet.on_create_alarm(
                         msg.cloud_account,
@@ -382,8 +390,8 @@
     them on to the tasklet.
     """
 
-    def __init__(self, tasklet):
-        super().__init__(tasklet)
+    def __init__(self, project):
+        super().__init__(project)
         self._handle = None
 
     @asyncio.coroutine
@@ -392,6 +400,9 @@
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
             try:
+                if not self.project.rpc_check(msg, xact_info=xact_info):
+                    return
+
                 yield from self.tasklet.on_destroy_alarm(
                         msg.cloud_account,
                         msg.alarm_id,
@@ -473,70 +484,31 @@
                 ])
 
 
-class MonitorTasklet(rift.tasklets.Tasklet):
-    """
-    The MonitorTasklet provides a interface for DTS to interact with an
-    instance of the Monitor class. This allows the Monitor class to remain
-    independent of DTS.
-    """
+class MonitorProject(ManoProject):
 
-    DEFAULT_POLLING_PERIOD = 1.0
+    def __init__(self, name, tasklet, **kw):
+        super(MonitorProject, self).__init__(log, name)
+        self._tasklet = tasklet
+        self._log_hdl = tasklet.log_hdl
+        self._dts = tasklet.dts
+        self._loop = tasklet.loop
 
-    def __init__(self, *args, **kwargs):
-        try:
-            super().__init__(*args, **kwargs)
-            self.rwlog.set_category("rw-monitor-log")
+        self.vnfr_subscriber = VnfrCatalogSubscriber(self)
+        self.cloud_cfg_subscriber = CloudAccountDtsHandler(self)
+        self.ns_instance_config_subscriber = NsInstanceConfigSubscriber(self)
+        self.launchpad_cfg_subscriber = LaunchpadConfigDtsSubscriber(self)
 
-            self.vnfr_subscriber = VnfrCatalogSubscriber(self)
-            self.cloud_cfg_subscriber = CloudAccountDtsHandler(self)
-            self.ns_instance_config_subscriber = NsInstanceConfigSubscriber(self)
-            self.launchpad_cfg_subscriber = LaunchpadConfigDtsSubscriber(self)
+        self.config = core.InstanceConfiguration()
+        self.config.polling_period = MonitorTasklet.DEFAULT_POLLING_PERIOD
 
-            self.config = core.InstanceConfiguration()
-            self.config.polling_period = MonitorTasklet.DEFAULT_POLLING_PERIOD
+        self.monitor = core.Monitor(self.loop, self.log, self.config, self)
+        self.vdur_handlers = dict()
 
-            self.monitor = core.Monitor(self.loop, self.log, self.config)
-            self.vdur_handlers = dict()
-
-            self.webhooks = None
-            self.create_alarm_rpc = CreateAlarmRPC(self)
-            self.destroy_alarm_rpc = DestroyAlarmRPC(self)
-
-
-        except Exception as e:
-            self.log.exception(e)
-
-    @property
-    def polling_period(self):
-        return self.config.polling_period
-
-    @property
-    def public_ip(self):
-        """The public IP of the launchpad"""
-        return self.config.public_ip
-
-    def start(self):
-        super().start()
-        self.log.info("Starting MonitoringTasklet")
-
-        self.log.debug("Registering with dts")
-        self.dts = rift.tasklets.DTS(
-                self.tasklet_info,
-                RwLaunchpadYang.get_schema(),
-                self.loop,
-                self.on_dts_state_change
-                )
-
-        self.log.debug("Created DTS Api GI Object: %s", self.dts)
-
-    def stop(self):
-      try:
-          self.dts.deinit()
-      except Exception as e:
-          self.log.exception(e)
+        self.create_alarm_rpc = CreateAlarmRPC(self)
+        self.destroy_alarm_rpc = DestroyAlarmRPC(self)
 
     @asyncio.coroutine
-    def init(self):
+    def register (self):
         self.log.debug("creating cloud account handler")
         self.cloud_cfg_subscriber.register()
 
@@ -555,23 +527,15 @@
         self.log.debug("creating destroy-alarm rpc handler")
         yield from self.destroy_alarm_rpc.register()
 
-        self.log.debug("creating webhook server")
-        loop = rift.tasklets.tornado.TaskletAsyncIOLoop(asyncio_loop=self.loop)
-        self.webhooks = WebhookApplication(self)
-        self.server = tornado.httpserver.HTTPServer(
-            self.webhooks,
-            io_loop=loop,
-        )
 
-    @asyncio.coroutine
-    def on_public_ip(self, ip):
-        """Store the public IP of the launchpad
+    @property
+    def polling_period(self):
+        return self.config.polling_period
 
-        Arguments:
-            ip - a string containing the public IP address of the launchpad
-
-        """
-        self.config.public_ip = ip
+    @property
+    def public_ip(self):
+        """The public IP of the launchpad"""
+        return self.config.public_ip
 
     def on_ns_instance_config_update(self, config):
         """Update configuration information
@@ -589,44 +553,6 @@
     def on_cloud_account_delete(self, account_name):
         self.monitor.remove_cloud_account(account_name)
 
-    @asyncio.coroutine
-    def run(self):
-        self.webhooks.listen(WebhookApplication.DEFAULT_WEBHOOK_PORT)
-
-    def on_instance_started(self):
-        self.log.debug("Got instance started callback")
-
-    @asyncio.coroutine
-    def on_dts_state_change(self, state):
-        """Handle DTS state change
-
-        Take action according to current DTS state to transition application
-        into the corresponding application state
-
-        Arguments
-            state - current dts state
-
-        """
-        switch = {
-            rwdts.State.INIT: rwdts.State.REGN_COMPLETE,
-            rwdts.State.CONFIG: rwdts.State.RUN,
-        }
-
-        handlers = {
-            rwdts.State.INIT: self.init,
-            rwdts.State.RUN: self.run,
-        }
-
-        # Transition application to next state
-        handler = handlers.get(state, None)
-        if handler is not None:
-            yield from handler()
-
-        # Transition dts to next state
-        next_state = switch.get(state, None)
-        if next_state is not None:
-            self.dts.handle.set_state(next_state)
-
     def on_vnfr_create(self, vnfr):
         if not self.monitor.nfvi_metrics_available(vnfr.cloud_account):
             msg = "NFVI metrics unavailable for {}"
@@ -712,3 +638,105 @@
 
         """
         yield from self.monitor.destroy_alarm(account, alarm_id)
+
+
+class MonitorTasklet(rift.tasklets.Tasklet):
+    """
+    The MonitorTasklet provides a interface for DTS to interact with an
+    instance of the Monitor class. This allows the Monitor class to remain
+    independent of DTS.
+    """
+
+    DEFAULT_POLLING_PERIOD = 1.0
+
+    def __init__(self, *args, **kwargs):
+        try:
+            super().__init__(*args, **kwargs)
+            self.rwlog.set_category("rw-monitor-log")
+
+            self._project_handler = None
+            self.projects = {}
+
+            self.webhooks = None
+
+        except Exception as e:
+            self.log.exception(e)
+
+    def start(self):
+        super().start()
+        self.log.info("Starting MonitoringTasklet")
+
+        self.log.debug("Registering with dts")
+        self.dts = rift.tasklets.DTS(
+                self.tasklet_info,
+                RwLaunchpadYang.get_schema(),
+                self.loop,
+                self.on_dts_state_change
+                )
+
+        self.log.debug("Created DTS Api GI Object: %s", self.dts)
+
+    def stop(self):
+      try:
+          self.dts.deinit()
+      except Exception as e:
+          self.log.exception(e)
+
+    @asyncio.coroutine
+    def init(self):
+        self.log.debug("creating webhook server")
+        loop = rift.tasklets.tornado.TaskletAsyncIOLoop(asyncio_loop=self.loop)
+        self.webhooks = WebhookApplication(self)
+        self.server = tornado.httpserver.HTTPServer(
+            self.webhooks,
+            io_loop=loop,
+        )
+
+    @asyncio.coroutine
+    def on_public_ip(self, ip):
+        """Store the public IP of the launchpad
+
+        Arguments:
+            ip - a string containing the public IP address of the launchpad
+
+        """
+        self.config.public_ip = ip
+
+    @asyncio.coroutine
+    def run(self):
+        self.webhooks.listen(WebhookApplication.DEFAULT_WEBHOOK_PORT)
+
+    def on_instance_started(self):
+        self.log.debug("Got instance started callback")
+
+    @asyncio.coroutine
+    def on_dts_state_change(self, state):
+        """Handle DTS state change
+
+        Take action according to current DTS state to transition application
+        into the corresponding application state
+
+        Arguments
+            state - current dts state
+
+        """
+        switch = {
+            rwdts.State.INIT: rwdts.State.REGN_COMPLETE,
+            rwdts.State.CONFIG: rwdts.State.RUN,
+        }
+
+        handlers = {
+            rwdts.State.INIT: self.init,
+            rwdts.State.RUN: self.run,
+        }
+
+        # Transition application to next state
+        handler = handlers.get(state, None)
+        if handler is not None:
+            yield from handler()
+
+        # Transition dts to next state
+        next_state = switch.get(state, None)
+        if next_state is not None:
+            self.dts.handle.set_state(next_state)
+
diff --git a/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/nsr_core.py b/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/nsr_core.py
index 78a3c8f..ce19580 100644
--- a/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/nsr_core.py
+++ b/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/nsr_core.py
@@ -42,22 +42,22 @@
         monp_id (str): Monitoring Param ID
         vnfr_id (str): VNFR ID
     """
-    def __init__(self, log, dts, loop, vnfr_id, monp_id, callback=None):
-        super().__init__(log, dts, loop, callback)
+    def __init__(self, log, dts, loop, project, vnfr_id, monp_id, callback=None):
+        super().__init__(log, dts, loop, project, callback)
         self.vnfr_id = vnfr_id
         self.monp_id = monp_id
 
     def get_xpath(self):
-        return("D,/vnfr:vnfr-catalog" +
+        return self.project.add_project(("D,/vnfr:vnfr-catalog" +
                "/vnfr:vnfr[vnfr:id='{}']".format(self.vnfr_id) +
                "/vnfr:monitoring-param" +
-               "[vnfr:id='{}']".format(self.monp_id))
+               "[vnfr:id='{}']".format(self.monp_id)))
 
 
 class NsrMonitoringParam():
     """Class that handles NS Mon-param data.
     """
-    MonParamMsg = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_MonitoringParam
+    MonParamMsg = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_MonitoringParam
     MISSING = None
     DEFAULT_AGGREGATION_TYPE = "AVERAGE"
 
@@ -66,7 +66,7 @@
         """Convenience class that constructs NSMonitoringParam objects
         
         Args:
-            nsd (RwNsdYang.YangData_Nsd_NsdCatalog_Nsd): Nsd object
+            nsd (RwNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd): Nsd object
             constituent_vnfrs (list): List of constituent vnfr objects of NSR
             store (SubscriberStore): Store object instance
         
@@ -76,8 +76,6 @@
         Also handles legacy NSD descriptor which has no mon-param defines. In
         such cases the mon-params are created from VNFD's mon-param config.
         """
-        MonParamMsg = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_MonitoringParam
-
         mon_params = []
         for mon_param_msg in nsd.monitoring_param:
             mon_params.append(NsrMonitoringParam(
@@ -278,16 +276,17 @@
     def from_handler(cls, handler, monp, callback):
         """Convenience class to build NsrMonitoringParamPoller object.
         """
-        return cls(handler.log, handler.dts, handler.loop, monp, callback)
+        return cls(handler.log, handler.dts, handler.loop, handler.project,
+                   monp, callback)
 
-    def __init__(self, log, dts, loop, monp, callback=None):
+    def __init__(self, log, dts, loop, project, monp, callback=None):
         """
         Args:
             monp (NsrMonitoringParam): Param object
             callback (None, optional): Callback to be triggered after value has
                 been aggregated.
         """
-        super().__init__(log, dts, loop)
+        super().__init__(log, dts, loop, project)
 
         self.monp = monp
         self.subscribers = []
@@ -341,7 +340,8 @@
         for vnfr_id, monp_id in self.monp.vnfr_ids:
             callback = functools.partial(self.update_value, vnfr_id=vnfr_id)
             self.subscribers.append(VnfrMonitoringParamSubscriber(
-                self.loop, self.dts, self.loop, vnfr_id, monp_id, callback=callback))
+                self.loop, self.dts, self.loop, self.project,
+                vnfr_id, monp_id, callback=callback))
 
     @asyncio.coroutine
     def start(self):
@@ -356,14 +356,14 @@
 class NsrMonitorDtsHandler(mano_dts.DtsHandler):
     """ NSR monitoring class """
 
-    def __init__(self, log, dts, loop, nsr, constituent_vnfrs, store):
+    def __init__(self, log, dts, loop, project, nsr, constituent_vnfrs, store):
         """
         Args:
-            nsr (RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr): NSR object
+            nsr (RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr): NSR object
             constituent_vnfrs (list): list of VNFRs in NSR
             store (SubscriberStore): Store instance
         """
-        super().__init__(log, dts, loop)
+        super().__init__(log, dts, loop, project)
 
         self.nsr = nsr
         self.store = store
@@ -371,7 +371,7 @@
         self.mon_params_pollers = []
 
     def xpath(self, param_id=None):
-        return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
+        return self.project.add_project("D,/nsr:ns-instance-opdata/nsr:nsr" +
             "[nsr:ns-instance-config-ref='{}']".format(self.nsr.ns_instance_config_ref) +
             "/nsr:monitoring-param" +
             ("[nsr:id='{}']".format(param_id) if param_id else ""))
diff --git a/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/rwmonparam.py b/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/rwmonparam.py
index 04e0306..2bfad6d 100644
--- a/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/rwmonparam.py
+++ b/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/rwmonparam.py
@@ -34,21 +34,20 @@
 import rift.mano.cloud
 import rift.mano.dts as subscriber
 import rift.tasklets
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+    )
 
 from . import vnfr_core
 from . import nsr_core
 
 
-class MonitoringParameterTasklet(rift.tasklets.Tasklet):
-    """The main task of this Tasklet is to listen for VNFR changes and once the
-    VNFR hits the running state, triggers the monitor.
-    """
-    def __init__(self, *args, **kwargs):
-        try:
-            super().__init__(*args, **kwargs)
-            self.rwlog.set_category("rw-monitor-log")
-        except Exception as e:
-            self.log.exception(e)
+class MonParamProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(MonParamProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
 
         self.vnfr_subscriber = None
         self.store = None
@@ -59,77 +58,27 @@
         # Needs to be moved to store once the DTS bug is resolved
         self.vnfrs = {}
 
-    def start(self):
-        super().start()
-
-        self.log.info("Starting MonitoringParameterTasklet")
-        self.log.debug("Registering with dts")
-
-        self.dts = rift.tasklets.DTS(
-                self.tasklet_info,
-                RwLaunchpadYang.get_schema(),
-                self.loop,
-                self.on_dts_state_change
-                )
-
-        self.vnfr_subscriber = subscriber.VnfrCatalogSubscriber.from_tasklet(
+        self.vnfr_subscriber = subscriber.VnfrCatalogSubscriber.from_project(
                 self,
                 callback=self.handle_vnfr)
-        self.nsr_subsriber = subscriber.NsrCatalogSubscriber.from_tasklet(
+        self.nsr_subsriber = subscriber.NsrCatalogSubscriber.from_project(
                 self,
                 callback=self.handle_nsr)
 
-        self.store = subscriber.SubscriberStore.from_tasklet(self)
+        self.store = subscriber.SubscriberStore.from_project(self)
 
         self.log.debug("Created DTS Api GI Object: %s", self.dts)
 
-    def stop(self):
-      try:
-          self.dts.deinit()
-      except Exception as e:
-          self.log.exception(e)
-
     @asyncio.coroutine
-    def init(self):
+    def register (self):
         self.log.debug("creating vnfr subscriber")
         yield from self.store.register()
         yield from self.vnfr_subscriber.register()
         yield from self.nsr_subsriber.register()
 
-    @asyncio.coroutine
-    def run(self):
-        pass
-
-    @asyncio.coroutine
-    def on_dts_state_change(self, state):
-        """Handle DTS state change
-
-        Take action according to current DTS state to transition application
-        into the corresponding application state
-
-        Arguments
-            state - current dts state
-
-        """
-        switch = {
-            rwdts.State.INIT: rwdts.State.REGN_COMPLETE,
-            rwdts.State.CONFIG: rwdts.State.RUN,
-        }
-
-        handlers = {
-            rwdts.State.INIT: self.init,
-            rwdts.State.RUN: self.run,
-        }
-
-        # Transition application to next state
-        handler = handlers.get(state, None)
-        if handler is not None:
-            yield from handler()
-
-        # Transition dts to next state
-        next_state = switch.get(state, None)
-        if next_state is not None:
-            self.dts.handle.set_state(next_state)
+    def deregister(self):
+        self.log.debug("De-register vnfr project {}".format(self.name))
+        #TODO:
 
     def handle_vnfr(self, vnfr, action):
         """Starts a monitoring parameter job for every VNFR that reaches
@@ -141,7 +90,6 @@
         """
 
         def vnfr_create():
-            # if vnfr.operational_status == "running" and vnfr.id not in self.vnfr_monitors:
             if vnfr.config_status == "configured" and vnfr.id not in self.vnfr_monitors:
 
                 vnf_mon = vnfr_core.VnfMonitorDtsHandler.from_vnf_data(
@@ -178,7 +126,7 @@
         NS that moves to config state.
 
         Args:
-            nsr (RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr): Ns Opdata
+            nsr (RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr): Ns Opdata
             action (rwdts.QueryAction): Action type of the change.
         """
         def nsr_create():
@@ -188,6 +136,7 @@
                         self.log,
                         self.dts,
                         self.loop,
+                        self,
                         nsr,
                         list(self.vnfrs.values()),
                         self.store
@@ -197,8 +146,12 @@
 
                 @asyncio.coroutine
                 def task():
-                    yield from nsr_mon.register()
-                    yield from nsr_mon.start()
+                    try:
+                        yield from nsr_mon.register()
+                        yield from nsr_mon.start()
+                    except Exception as e:
+                        self.log.exception("NSR {} monparam task failed: {}".
+                                           format(nsr.name_ref, e))
 
                 self.loop.create_task(task())
 
@@ -214,3 +167,78 @@
             nsr_create()
         elif action == rwdts.QueryAction.DELETE:
             nsr_delete()
+
+
+class MonitoringParameterTasklet(rift.tasklets.Tasklet):
+    """The main task of this Tasklet is to listen for VNFR changes and once the
+    VNFR hits the running state, triggers the monitor.
+    """
+    def __init__(self, *args, **kwargs):
+        try:
+            super().__init__(*args, **kwargs)
+            self.rwlog.set_category("rw-monitor-log")
+        except Exception as e:
+            self.log.exception(e)
+
+        self._project_handler = None
+        self.projects = {}
+
+    def start(self):
+        super().start()
+
+        self.log.info("Starting MonitoringParameterTasklet")
+        self.log.debug("Registering with dts")
+
+        self.dts = rift.tasklets.DTS(
+                self.tasklet_info,
+                RwLaunchpadYang.get_schema(),
+                self.loop,
+                self.on_dts_state_change
+                )
+
+    def stop(self):
+      try:
+          self.dts.deinit()
+      except Exception as e:
+          self.log.exception(e)
+
+    @asyncio.coroutine
+    def init(self):
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, MonParamProject)
+        self.project_handler.register()
+
+    @asyncio.coroutine
+    def run(self):
+        pass
+
+    @asyncio.coroutine
+    def on_dts_state_change(self, state):
+        """Handle DTS state change
+
+        Take action according to current DTS state to transition application
+        into the corresponding application state
+
+        Arguments
+            state - current dts state
+
+        """
+        switch = {
+            rwdts.State.INIT: rwdts.State.REGN_COMPLETE,
+            rwdts.State.CONFIG: rwdts.State.RUN,
+        }
+
+        handlers = {
+            rwdts.State.INIT: self.init,
+            rwdts.State.RUN: self.run,
+        }
+
+        # Transition application to next state
+        handler = handlers.get(state, None)
+        if handler is not None:
+            yield from handler()
+
+        # Transition dts to next state
+        next_state = switch.get(state, None)
+        if next_state is not None:
+            self.dts.handle.set_state(next_state)
diff --git a/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/vnfr_core.py b/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/vnfr_core.py
index 6dc3a25..335e957 100644
--- a/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/vnfr_core.py
+++ b/rwlaunchpad/plugins/rwmonparam/rift/tasklets/rwmonparam/vnfr_core.py
@@ -616,29 +616,29 @@
     XPATH = "D,/vnfr:vnfr-catalog/vnfr:vnfr/vnfr:monitoring-param"
 
     @classmethod
-    def from_vnf_data(cls, tasklet, vnfr_msg, vnfd_msg):
-        handler = cls(tasklet.log, tasklet.dts, tasklet.loop,
+    def from_vnf_data(cls, project, vnfr_msg, vnfd_msg):
+        handler = cls(project.log, project.dts, project.loop, project,
                 vnfr_msg.id, vnfr_msg.mgmt_interface.ip_address,
                 vnfd_msg.monitoring_param, vnfd_msg.http_endpoint)
 
         return handler
 
-    def __init__(self, log, dts, loop, vnfr_id, mgmt_ip, params, endpoints):
-        super().__init__(log, dts, loop)
+    def __init__(self, log, dts, loop, project, vnfr_id, mgmt_ip, params, endpoints):
+        super().__init__(log, dts, loop, project)
 
         self._mgmt_ip = mgmt_ip
         self._vnfr_id = vnfr_id
 
         mon_params = []
         for mon_param in params:
-            param = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MonitoringParam.from_dict(
+            param = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam.from_dict(
                     mon_param.as_dict()
                     )
             mon_params.append(param)
 
         http_endpoints = []
         for endpoint in endpoints:
-            endpoint = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_HttpEndpoint.from_dict(
+            endpoint = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_HttpEndpoint.from_dict(
                     endpoint.as_dict()
                     )
             http_endpoints.append(endpoint)
@@ -674,10 +674,10 @@
 
     def xpath(self, param_id=None):
         """ Monitoring params xpath """
-        return("D,/vnfr:vnfr-catalog" +
+        return self.project.add_project(("D,/vnfr:vnfr-catalog" +
                "/vnfr:vnfr[vnfr:id='{}']".format(self._vnfr_id) +
                "/vnfr:monitoring-param" +
-               ("[vnfr:id='{}']".format(param_id) if param_id else ""))
+               ("[vnfr:id='{}']".format(param_id) if param_id else "")))
 
     @property
     def msg(self):
diff --git a/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params.py b/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params.py
index fd48952..c99fc00 100755
--- a/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params.py
+++ b/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params.py
@@ -54,7 +54,7 @@
             'ping-response-rx-count': 10
             }
 
-    mon_param_msg = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MonitoringParam()
+    mon_param_msg = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam()
     mon_param_msg.from_dict({
             'id': '1',
             'name': 'ping-request-tx-count',
@@ -67,7 +67,7 @@
             'units': 'packets'
             })
 
-    endpoint_msg = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_HttpEndpoint()
+    endpoint_msg = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_HttpEndpoint()
     endpoint_msg.from_dict({
         'path': ping_path,
         'polling_interval_secs': 1,
@@ -231,7 +231,7 @@
             'ping-response-rx-count': 10
             }
 
-    mon_param_msg = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MonitoringParam()
+    mon_param_msg = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam()
     mon_param_msg.from_dict({
             'id': '1',
             'name': 'ping-request-tx-count',
@@ -244,7 +244,7 @@
             'units': 'packets'
             })
 
-    endpoint_msg = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_HttpEndpoint()
+    endpoint_msg = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_HttpEndpoint()
     endpoint_msg.from_dict({
         'path': ping_path,
         'https': 'true',
diff --git a/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params_dts.py b/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params_dts.py
index fb0b039..80d9387 100644
--- a/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params_dts.py
+++ b/rwlaunchpad/plugins/rwmonparam/test/utest_mon_params_dts.py
@@ -50,7 +50,7 @@
 class MonParamMsgGenerator(object):
     def __init__(self, num_messages=1):
         ping_path = r"/api/v1/ping/stats"
-        self._endpoint_msg = vnfryang.YangData_Vnfr_VnfrCatalog_Vnfr_HttpEndpoint.from_dict({
+        self._endpoint_msg = vnfryang.YangData_RwProject_Project_VnfrCatalog_Vnfr_HttpEndpoint.from_dict({
             'path': ping_path,
             'https': 'true',
             'polling_interval_secs': 1,
@@ -61,7 +61,7 @@
 
         self._mon_param_msgs = []
         for i in range(1, num_messages):
-            self._mon_param_msgs.append(vnfryang.YangData_Vnfr_VnfrCatalog_Vnfr_MonitoringParam.from_dict({
+            self._mon_param_msgs.append(vnfryang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam.from_dict({
                 'id': '%s' % i,
                 'name': 'param_num_%s' % i,
                 'json_query_method': "NAMEKEY",
@@ -127,7 +127,7 @@
     def setup_mock_store(self, aggregation_type, monps, legacy=False):
         store = mock.MagicMock()
 
-        mock_vnfd =  RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd.from_dict({
+        mock_vnfd =  RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd.from_dict({
             'id': "1",
             'monitoring_param': [
                 {'description': 'no of ping requests',
@@ -151,14 +151,14 @@
             })
         store.get_vnfd = mock.MagicMock(return_value=mock_vnfd)
 
-        mock_vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict({
+        mock_vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.from_dict({
             'id': '1',
             'monitoring_param': ([monp.as_dict() for monp in monps] if not legacy else [])
             })
-        mock_vnfr.vnfd = vnfryang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict({'id': '1'})
+        mock_vnfr.vnfd = vnfryang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vnfd.from_dict({'id': '1'})
         store.get_vnfr = mock.MagicMock(return_value=mock_vnfr)
 
-        mock_nsr = RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr.from_dict({
+        mock_nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr.from_dict({
             'ns_instance_config_ref': "1",
             'name_ref': "Foo",
             'constituent_vnfr_ref': [{'vnfr_id': mock_vnfr.id}],
@@ -182,7 +182,7 @@
                      'vnfd_monitoring_param_ref': '2'}]
                 }]
 
-        mock_nsd = RwNsdYang.YangData_Nsd_NsdCatalog_Nsd.from_dict({
+        mock_nsd = RwNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd.from_dict({
             'id': str(uuid.uuid1()),
             'monitoring_param': (monp if not legacy else [])
             })
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py
index 007e62c..ef7856d 100644
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/cloud.py
@@ -128,15 +128,17 @@
 
 
 class CloudAccountConfigSubscriber:
-    def __init__(self, log, dts, log_hdl):
+    def __init__(self, log, dts, log_hdl, project):
         self._dts = dts
         self._log = log
         self._log_hdl = log_hdl
+        self._project = project
 
         self._cloud_sub = rift.mano.cloud.CloudAccountConfigSubscriber(
                 self._dts,
                 self._log,
                 self._log_hdl,
+                self._project,
                 rift.mano.cloud.CloudAccountConfigCallbacks())
 
     def get_cloud_account_sdn_name(self, account_name):
@@ -154,6 +156,9 @@
     def register(self):
        self._cloud_sub.register()
 
+    def deregister(self):
+       self._cloud_sub.deregister()
+
 
 class ROAccountPluginSelector(object):
     """
@@ -166,10 +171,11 @@
     """
     DEFAULT_PLUGIN = RwNsPlugin
 
-    def __init__(self, dts, log, loop, records_publisher):
+    def __init__(self, dts, log, loop, project, records_publisher):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._records_publisher = records_publisher
 
         self._nsm_plugins = NsmPlugins()
@@ -178,12 +184,14 @@
                 self._log,
                 self._dts,
                 self._loop,
+                self._project,
                 callback=self.on_ro_account_change
                 )
         self._nsr_sub = mano_dts.NsrCatalogSubscriber(
                 self._log,
                 self._dts,
                 self._loop,
+                self._project,
                 self.handle_nsr)
 
         # The default plugin will be RwNsPlugin
@@ -240,3 +248,8 @@
     def register(self):
         yield from self._ro_sub.register()
         yield from self._nsr_sub.register()
+
+    def deregister(self):
+        self._log.debug("Project {} de-register".format(self._project.name))
+        self._ro_sub.deregister()
+        self._nsr_sub.deregister()
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py
index d53d701..0fcd905 100644
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py
@@ -102,7 +102,7 @@
                 )
 
             if action == rwdts.QueryAction.READ:
-                schema = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur.schema()
+                schema = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
 
                 try:
@@ -118,7 +118,7 @@
                                         self._nsr._nsr_uuid,
                                         self._vdur_id
                                        )
-                    vdur_console = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur()
+                    vdur_console = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur()
                     vdur_console.id = self._vdur_id
                     if console_url:
                         vdur_console.console_url = console_url
@@ -128,7 +128,7 @@
                 except openmano_client.InstanceStatusError as e:
                     self._log.error("Could not get NS instance console URL: %s",
                                         str(e))
-                    vdur_console = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur()
+                    vdur_console = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur()
                     vdur_console.id = self._vdur_id
                     vdur_console.console_url = 'none'
 
@@ -885,7 +885,7 @@
 
     def vnfr_uptime_update(self, vnfr):
         try:
-            vnfr_ = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict({'id': vnfr.id})
+            vnfr_ = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.from_dict({'id': vnfr.id})
             while True:
                 vnfr_.uptime = int(time.time()) - vnfr._create_time
                 yield from self._publisher.publish_vnfr(None, vnfr_)
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/publisher.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/publisher.py
index 6c4b123..e3ae5cf 100644
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/publisher.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/publisher.py
@@ -33,10 +33,11 @@
     """ The network service op data DTS handler """
     XPATH = "D,/nsr:ns-instance-opdata/nsr:nsr"
 
-    def __init__(self, dts, log, loop):
+    def __init__(self, dts, log, loop, project):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._regh = None
 
     @property
@@ -47,38 +48,45 @@
     @asyncio.coroutine
     def register(self):
         """ Register for Nsr op data publisher registration"""
-        self._log.debug("Registering Nsr op data path %s as publisher",
-                        NsrOpDataDtsHandler.XPATH)
+        if self._regh:
+            return
+
+        xpath = self._project.add_project(NsrOpDataDtsHandler.XPATH)
+        self._log.debug("Registering Nsr op data path {} as publisher".
+                        format(xpath))
 
         hdl = rift.tasklets.DTS.RegistrationHandler()
         with self._dts.group_create() as group:
-            self._regh = group.register(xpath=NsrOpDataDtsHandler.XPATH,
+            self._regh = group.register(xpath=xpath,
                                         handler=hdl,
                                         flags=rwdts.Flag.PUBLISHER | rwdts.Flag.NO_PREP_READ)
 
     @asyncio.coroutine
-    def create(self, xact, path, msg):
+    def create(self, xact, xpath, msg):
         """
         Create an NS record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Creating NSR xact = %s, %s:%s", xact, path, msg)
         self.regh.create_element(path, msg)
         self._log.debug("Created NSR xact = %s, %s:%s", xact, path, msg)
 
     @asyncio.coroutine
-    def update(self, xact, path, msg, flags=rwdts.XactFlag.REPLACE):
+    def update(self, xact, xpath, msg, flags=rwdts.XactFlag.REPLACE):
         """
         Update an NS record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Updating NSR xact = %s, %s:%s regh = %s", xact, path, msg, self.regh)
         self.regh.update_element(path, msg, flags)
         self._log.debug("Updated NSR xact = %s, %s:%s", xact, path, msg)
 
     @asyncio.coroutine
-    def delete(self, xact, path):
+    def delete(self, xact, xpath):
         """
         Update an NS record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Deleting NSR xact:%s, path:%s", xact, path)
         self.regh.delete_element(path)
         self._log.debug("Deleted NSR xact:%s, path:%s", xact, path)
@@ -86,13 +94,14 @@
 
 
 class VnfrPublisherDtsHandler(object):
-    """ Registers 'D,/vnfr:vnfr-catalog/vnfr:vnfr' DTS"""
+    """ Registers 'D,/rw-project:project/vnfr:vnfr-catalog/vnfr:vnfr' DTS"""
     XPATH = "D,/vnfr:vnfr-catalog/vnfr:vnfr"
 
-    def __init__(self, dts, log, loop):
+    def __init__(self, dts, log, loop, project):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
 
         self._regh = None
 
@@ -104,6 +113,8 @@
     @asyncio.coroutine
     def register(self):
         """ Register for Vvnfr create/update/delete/read requests from dts """
+        if self._regh:
+            return
 
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
@@ -116,12 +127,13 @@
                 "%s action on VirtualNetworkFunctionRecord not supported",
                 action)
 
-        self._log.debug("Registering for VNFR using xpath: %s",
-                        VnfrPublisherDtsHandler.XPATH,)
+        xpath = self._project.add_project(VnfrPublisherDtsHandler.XPATH)
+        self._log.debug("Registering for VNFR using xpath: {}".
+                        format(xpath))
 
         hdl = rift.tasklets.DTS.RegistrationHandler()
         with self._dts.group_create() as group:
-            self._regh = group.register(xpath=VnfrPublisherDtsHandler.XPATH,
+            self._regh = group.register(xpath=xpath,
                                         handler=hdl,
                                         flags=(rwdts.Flag.PUBLISHER |
                                                rwdts.Flag.NO_PREP_READ |
@@ -160,13 +172,14 @@
 
 
 class VlrPublisherDtsHandler(object):
-    """ registers 'D,/vlr:vlr-catalog/vlr:vlr """
+    """ registers 'D,/rw-project:project/vlr:vlr-catalog/vlr:vlr """
     XPATH = "D,/vlr:vlr-catalog/vlr:vlr"
 
-    def __init__(self, dts, log, loop):
+    def __init__(self, dts, log, loop, project):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
 
         self._regh = None
 
@@ -179,6 +192,9 @@
     def register(self):
         """ Register for vlr create/update/delete/read requests from dts """
 
+        if self._regh:
+            return
+
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
             """ prepare callback from dts """
@@ -190,12 +206,13 @@
                 "%s action on VirtualLinkRecord not supported",
                 action)
 
-        self._log.debug("Registering for VLR using xpath: %s",
-                        VlrPublisherDtsHandler.XPATH,)
+        xpath = self._project.add_project(VlrPublisherDtsHandler.XPATH)
+        self._log.debug("Registering for VLR using xpath: {}".
+                        format(xpath))
 
         hdl = rift.tasklets.DTS.RegistrationHandler()
         with self._dts.group_create() as group:
-            self._regh = group.register(xpath=VlrPublisherDtsHandler.XPATH,
+            self._regh = group.register(xpath=xpath,
                                         handler=hdl,
                                         flags=(rwdts.Flag.PUBLISHER |
                                                rwdts.Flag.NO_PREP_READ |
@@ -238,10 +255,11 @@
     HEADERS = {"content-type": "application/vnd.yang.data+json"}
 
 
-    def __init__(self, use_ssl, ssl_cert, ssl_key, loop):
+    def __init__(self, use_ssl, ssl_cert, ssl_key, loop, project):
         self.use_ssl = use_ssl
         self.ssl_cert = ssl_cert
         self.ssl_key = ssl_key
+        self._project = project
         self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
         self.loop = loop
 
@@ -255,7 +273,7 @@
 
             scheme = "https" if self.use_ssl else "http"
 
-            url = "{}://127.0.0.1:8008/api/config/vnfd-catalog/vnfd/{}"
+            url = "{}://127.0.0.1:8008/api/config/project/{}/vnfd-catalog/vnfd/{}"
 
             model = RwYang.Model.create_libncx()
             model.load_module("rw-vnfd")
@@ -277,7 +295,7 @@
                 options["cert"] = (self.ssl_cert, self.ssl_key)
 
             response = requests.put(
-                url.format(scheme, vnfd.id),
+                url.format(scheme, self._project.name, vnfd.id),
                 **options
             )
 
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsm_conman.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsm_conman.py
index 23ab7b6..1988cc4 100644
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsm_conman.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsm_conman.py
@@ -46,6 +46,7 @@
         self._loop = loop
         self._dts = dts
         self.nsm = parent
+        self.project = parent._project
         self._log.debug("Initialized ROConfigManager")
 
     def is_ready(self):
@@ -53,7 +54,7 @@
 
     @property
     def cm_state_xpath(self):
-        return ("/rw-conman:cm-state/rw-conman:cm-nsr")
+        return self.project.add_project("/rw-conman:cm-state/rw-conman:cm-nsr")
 
     @classmethod
     def map_config_status(cls, status):
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py
index 3153a48..0797b55 100755
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py
@@ -61,6 +61,12 @@
 import rift.mano.ncclient
 import rift.mano.config_data.config
 import rift.mano.dts as mano_dts
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+    get_add_delete_update_cfgs,
+    DEFAULT_PROJECT,
+    )
 
 from . import rwnsm_conman as conman
 from . import cloud
@@ -225,7 +231,7 @@
                            "sdn_account": self._sdn_account_name,
                            "operational_status": 'init',
                            }
-            vnffgr = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
+            vnffgr = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
         elif self._vnffgr_state == VnffgRecordState.TERMINATED:
             vnffgr_dict = {"id": self._vnffgr_id,
                            "vnffgd_id_ref": self._vnffgd_msg.id,
@@ -233,7 +239,7 @@
                            "sdn_account": self._sdn_account_name,
                            "operational_status": 'terminated',
                            }
-            vnffgr = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
+            vnffgr = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
         else:
             try:
                 vnffgr = self._vnffgmgr.fetch_vnffgr(self._vnffgr_id)
@@ -246,7 +252,7 @@
                                "sdn_account": self._sdn_account_name,
                                "operational_status": 'failed',
                                }
-                vnffgr = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
+                vnffgr = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
 
         return vnffgr
 
@@ -258,7 +264,7 @@
                        "vnffgd_name_ref": self._vnffgd_msg.name,
                        "sdn_account": self._sdn_account_name,
                     }
-        vnffgr = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
+        vnffgr = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_Vnffgr.from_dict(vnffgr_dict)
         for rsp in self._vnffgd_msg.rsp:
             vnffgr_rsp = vnffgr.rsp.add()
             vnffgr_rsp.id = str(uuid.uuid4())
@@ -270,9 +276,11 @@
                 vnfd =  [vnfr.vnfd for vnfr in self._nsr.vnfrs.values() if vnfr.vnfd.id == rsp_cp_ref.vnfd_id_ref]
                 self._log.debug("VNFD message during VNFFG instantiation is %s",vnfd)
                 if len(vnfd) > 0 and vnfd[0].has_field('service_function_type'):
-                    self._log.debug("Service Function Type for VNFD ID %s is %s",rsp_cp_ref.vnfd_id_ref, vnfd[0].service_function_type)
+                    self._log.debug("Service Function Type for VNFD ID %s is %s",
+                                    rsp_cp_ref.vnfd_id_ref, vnfd[0].service_function_type)
                 else:
-                    self._log.error("Service Function Type not available for VNFD ID %s; Skipping in chain",rsp_cp_ref.vnfd_id_ref)
+                    self._log.error("Service Function Type not available for VNFD ID %s; Skipping in chain",
+                                    rsp_cp_ref.vnfd_id_ref)
                     continue
 
                 vnfr_cp_ref =  vnffgr_rsp.vnfr_connection_point_ref.add()
@@ -293,7 +301,8 @@
                            self._log.info("Received vnf op status is %s; retrying",vnfr.operational_status)
                            if vnfr.operational_status == 'failed':
                                self._log.error("Fetching VNFR for  %s failed", vnfr.id)
-                               raise NsrInstantiationFailed("Failed NS %s instantiation due to VNFR %s failure" % (self.id, vnfr.id))
+                               raise NsrInstantiationFailed("Failed NS %s instantiation due to VNFR %s failure" %
+                                                            (self.id, vnfr.id))
                            yield from asyncio.sleep(2, loop=self._loop)
                            vnfr = yield from self._nsr.fetch_vnfr(nsr_vnfr.xpath)
                            self._log.debug("Received VNFR is %s", vnfr)
@@ -320,7 +329,8 @@
                 rsp_id_ref = _rsp[0].id
                 rsp_name = _rsp[0].name
             else:
-                self._log.error("RSP with ID %s not found during classifier creation for classifier id %s",vnffgd_classifier.rsp_id_ref,vnffgd_classifier.id)
+                self._log.error("RSP with ID %s not found during classifier creation for classifier id %s",
+                                vnffgd_classifier.rsp_id_ref,vnffgd_classifier.id)
                 continue
             vnffgr_classifier = vnffgr.classifier.add()
             vnffgr_classifier.id = vnffgd_classifier.id
@@ -344,7 +354,8 @@
                            self._log.info("Received vnf op status is %s; retrying",vnfr.operational_status)
                            if vnfr.operational_status == 'failed':
                                self._log.error("Fetching VNFR for  %s failed", vnfr.id)
-                               raise NsrInstantiationFailed("Failed NS %s instantiation due to VNFR %s failure" % (self.id, vnfr.id))
+                               raise NsrInstantiationFailed("Failed NS %s instantiation due to VNFR %s failure" %
+                                                            (self.id, vnfr.id))
                            yield from asyncio.sleep(2, loop=self._loop)
                            vnfr = yield from self._nsr.fetch_vnfr(nsr_vnfr.xpath)
                            self._log.debug("Received VNFR is %s", vnfr)
@@ -357,8 +368,9 @@
                                    for ext_intf in vdu.external_interface:
                                        if ext_intf.name == vnffgr_classifier.vnfr_connection_point_ref:
                                            vnffgr_classifier.vm_id =  vdu.vim_id
-                                           self._log.debug("VIM ID for CP %s in VNFR %s is %s",cp.name,nsr_vnfr.id,
-                                                            vnfr_cp_ref.connection_point_params.vm_id)
+                                           self._log.debug("VIM ID for CP %s in VNFR %s is %s",
+                                                           cp.name,nsr_vnfr.id,
+                                                           vnfr_cp_ref.connection_point_params.vm_id)
                                            break
 
         self._log.info("VNFFGR msg to be sent is %s", vnffgr)
@@ -459,7 +471,9 @@
     XPATH = "D,/vlr:vlr-catalog/vlr:vlr"
     @staticmethod
     @asyncio.coroutine
-    def create_record(dts, log, loop, nsr_name, vld_msg, cloud_account_name, om_datacenter, ip_profile, nsr_id, restart_mode=False):
+    def create_record(dts, log, loop, project, nsr_name, vld_msg,
+                      cloud_account_name, om_datacenter, ip_profile,
+                      nsr_id, restart_mode=False):
         """Creates a new VLR object based on the given data.
 
         If restart mode is enabled, then we look for existing records in the
@@ -472,6 +486,7 @@
                       dts,
                       log,
                       loop,
+                      project,
                       nsr_name,
                       vld_msg,
                       cloud_account_name,
@@ -482,7 +497,7 @@
 
         if restart_mode:
             res_iter = yield from dts.query_read(
-                              "D,/vlr:vlr-catalog/vlr:vlr",
+                              project.add_project("D,/vlr:vlr-catalog/vlr:vlr"),
                               rwdts.XactFlag.MERGE)
 
             for fut in res_iter:
@@ -498,10 +513,12 @@
 
         return vlr_obj
 
-    def __init__(self, dts, log, loop, nsr_name, vld_msg, cloud_account_name, om_datacenter, ip_profile, nsr_id):
+    def __init__(self, dts, log, loop, project, nsr_name, vld_msg,
+                 cloud_account_name, om_datacenter, ip_profile, nsr_id):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._nsr_name = nsr_name
         self._vld_msg = vld_msg
         self._cloud_account_name = cloud_account_name
@@ -517,7 +534,8 @@
     @property
     def xpath(self):
         """ path for this object """
-        return "D,/vlr:vlr-catalog/vlr:vlr[vlr:id = '{}']".format(self._vlr_id)
+        return self._project.add_project("D,/vlr:vlr-catalog/vlr:vlr[vlr:id = '{}']".
+                                         format(self._vlr_id))
 
     @property
     def id(self):
@@ -615,7 +633,7 @@
             vlr_dict['ip_profile_params' ] = self._ip_profile.ip_profile_params.as_dict()
 
         vlr_dict.update(vld_copy_dict)
-        vlr = RwVlrYang.YangData_Vlr_VlrCatalog_Vlr.from_dict(vlr_dict)
+        vlr = RwVlrYang.YangData_RwProject_Project_VlrCatalog_Vlr.from_dict(vlr_dict)
         return vlr
 
     def reset_id(self, vlr_id):
@@ -623,7 +641,7 @@
 
     def create_nsr_vlr_msg(self, vnfrs):
         """ The VLR message"""
-        nsr_vlr = RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_Vlr()
+        nsr_vlr = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_Vlr()
         nsr_vlr.vlr_ref = self._vlr_id
         nsr_vlr.assigned_subnet = self.assigned_subnet
         nsr_vlr.cloud_account = self.cloud_account_name
@@ -721,7 +739,7 @@
 
     @staticmethod
     @asyncio.coroutine
-    def create_record(dts, log, loop, vnfd, const_vnfd_msg, nsd_id, nsr_name,
+    def create_record(dts, log, loop, project, vnfd, const_vnfd_msg, nsd_id, nsr_name,
                 cloud_account_name, om_datacenter_name, nsr_id, group_name, group_instance_id,
                 placement_groups, restart_mode=False):
         """Creates a new VNFR object based on the given data.
@@ -736,6 +754,7 @@
                           dts,
                           log,
                           loop,
+                          project,
                           vnfd,
                           const_vnfd_msg,
                           nsd_id,
@@ -750,7 +769,7 @@
 
         if restart_mode:
             res_iter = yield from dts.query_read(
-                              "D,/vnfr:vnfr-catalog/vnfr:vnfr",
+                              project.add_project("D,/vnfr:vnfr-catalog/vnfr:vnfr"),
                               rwdts.XactFlag.MERGE)
 
             for fut in res_iter:
@@ -767,6 +786,7 @@
                  dts,
                  log,
                  loop,
+                 project,
                  vnfd,
                  const_vnfd_msg,
                  nsd_id,
@@ -781,6 +801,7 @@
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._vnfd = vnfd
         self._const_vnfd_msg = const_vnfd_msg
         self._nsd_id = nsd_id
@@ -820,7 +841,8 @@
     @property
     def xpath(self):
         """ VNFR xpath """
-        return "D,/vnfr:vnfr-catalog/vnfr:vnfr[vnfr:id = '{}']".format(self.id)
+        return self._project.add_project("D,/vnfr:vnfr-catalog/vnfr:vnfr[vnfr:id = '{}']"
+                                         .format(self.id))
 
     @property
     def vnfr_msg(self):
@@ -830,7 +852,9 @@
     @property
     def const_vnfr_msg(self):
         """ VNFR message """
-        return RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_ConstituentVnfrRef(vnfr_id=self.id,cloud_account=self.cloud_account_name,om_datacenter=self._om_datacenter_name)
+        return RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_ConstituentVnfrRef(
+            vnfr_id=self.id, cloud_account=self.cloud_account_name,
+            om_datacenter=self._om_datacenter_name)
 
     @property
     def vnfd(self):
@@ -896,7 +920,8 @@
     @staticmethod
     def vnfr_xpath(vnfr):
         """ Get the VNFR path from VNFR """
-        return (VirtualNetworkFunctionRecord.XPATH + "[vnfr:id = '{}']").format(vnfr.id)
+        return (self._project.add_project(VirtualNetworkFunctionRecord.XPATH) +
+                "[vnfr:id = '{}']").format(vnfr.id)
 
     @property
     def config_type(self):
@@ -956,10 +981,11 @@
                 }
         vnfr_dict.update(vnfd_copy_dict)
 
-        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict(vnfr_dict)
-        vnfr.vnfd = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict(),
-                                                                          ignore_missing_keys=True)
-        vnfr.member_vnf_index_ref = self.member_vnf_index
+        vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.from_dict(vnfr_dict)
+        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.vnf_configuration.from_dict(self._vnfd.vnf_configuration.as_dict())
 
         if self._vnfd.mgmt_interface.has_field("port"):
@@ -981,7 +1007,7 @@
                         format(self.name, self.vnfr_msg))
         yield from self._dts.query_update(
                 self.xpath,
-                rwdts.XactFlag.TRACE,
+                0, #rwdts.XactFlag.TRACE,
                 self.vnfr_msg
                 )
 
@@ -1069,7 +1095,7 @@
 
         # For every connection point in the VNFD fill in the identifier
         for conn_p in self._vnfd.connection_point:
-            cpr = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_ConnectionPoint()
+            cpr = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_ConnectionPoint()
             cpr.name = conn_p.name
             cpr.type_yang = conn_p.type_yang
             if conn_p.has_field('port_security_enabled'):
@@ -1222,7 +1248,7 @@
         event_list = []
         idx = 1
         for entry in self._events:
-            event = RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_OperationalEvents()
+            event = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_OperationalEvents()
             event.id = idx
             idx += 1
             event.timestamp, event.event, event.description, event.details = entry
@@ -1234,7 +1260,8 @@
     """ Network service record """
     XPATH = "D,/nsr:ns-instance-opdata/nsr:nsr"
 
-    def __init__(self, dts, log, loop, nsm, nsm_plugin, nsr_cfg_msg, sdn_account_name, key_pairs, restart_mode=False,
+    def __init__(self, dts, log, loop, nsm, nsm_plugin, nsr_cfg_msg,
+                 sdn_account_name, key_pairs, project, restart_mode=False,
                  vlr_handler=None):
         self._dts = dts
         self._log = log
@@ -1244,6 +1271,7 @@
         self._nsm_plugin = nsm_plugin
         self._sdn_account_name = sdn_account_name
         self._vlr_handler = vlr_handler
+        self._project = project
 
         self._nsd = None
         self._nsr_msg = None
@@ -1277,7 +1305,7 @@
 
         self.set_state(NetworkServiceRecordState.INIT)
 
-        self.substitute_input_parameters = InputParameterSubstitution(self._log)
+        self.substitute_input_parameters = InputParameterSubstitution(self._log, self._project)
 
     @property
     def nsm_plugin(self):
@@ -1393,7 +1421,7 @@
 
         for group_info in self._nsr_cfg_msg.nsd_placement_group_maps:
             if group_info.placement_group_ref == input_group.name:
-                group = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_PlacementGroupsInfo()
+                group = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_PlacementGroupsInfo()
                 group_dict = {k:v for k,v in
                               group_info.as_dict().items() if k != 'placement_group_ref'}
                 for param in copy_dict:
@@ -1465,14 +1493,16 @@
     def vlr_uptime_update(self, vlr):
         try:
 
-            vlr_ = RwVlrYang.YangData_Vlr_VlrCatalog_Vlr.from_dict({'id': vlr.id})
+            vlr_ = RwVlrYang.YangData_RwProject_Project_VlrCatalog_Vlr.from_dict({'id': vlr.id})
             while True:
                 vlr_.uptime = int(time.time()) - vlr._create_time
-                yield from self._vlr_handler.update(None, VirtualLinkRecord.vlr_xpath(vlr), vlr_)
+                xpath = self._project.add_project(VirtualLinkRecord.vlr_xpath(vlr))
+                yield from self._vlr_handler.update(None, xpath, vlr_)
                 yield from asyncio.sleep(2, loop=self._loop)
         except asyncio.CancelledError:
             self._log.debug("Received cancellation request for vlr_uptime_update task")
-            yield from self._vlr_handler.delete(None, VirtualLinkRecord.vlr_xpath(vlr))
+            xpath = self._project.add_project(VirtualLinkRecord.vlr_xpath(vlr))
+            yield from self._vlr_handler.delete(None, xpath)
 
 
     @asyncio.coroutine
@@ -1850,6 +1880,7 @@
                 self._dts,
                 self._log,
                 self._loop,
+                self._project,
                 self.name,
                 vld,
                 cloud_account,
@@ -2033,6 +2064,7 @@
         vnfr = yield from VirtualNetworkFunctionRecord.create_record(self._dts,
                                             self._log,
                                             self._loop,
+                                            self._project,
                                             vnfd_msg,
                                             const_vnfd,
                                             self.nsd_id,
@@ -2188,23 +2220,23 @@
     @property
     def nsr_xpath(self):
         """ Returns the xpath associated with this NSR """
-        return(
+        return self._project.add_project((
             "D,/nsr:ns-instance-opdata" +
             "/nsr:nsr[nsr:ns-instance-config-ref = '{}']"
-            ).format(self.id)
+        ).format(self.id))
 
     @staticmethod
     def xpath_from_nsr(nsr):
         """ Returns the xpath associated with this NSR  op data"""
-        return (NetworkServiceRecord.XPATH +
-                "[nsr:ns-instance-config-ref = '{}']").format(nsr.id)
+        return self._project.add_project((NetworkServiceRecord.XPATH +
+                    "[nsr:ns-instance-config-ref = '{}']").format(nsr.id))
 
     @property
     def nsd_xpath(self):
         """ Return NSD config xpath."""
-        return(
+        return self._project.add_project((
             "C,/nsd:nsd-catalog/nsd:nsd[nsd:id = '{}']"
-            ).format(self.nsd_id)
+        ).format(self.nsd_id))
 
     @asyncio.coroutine
     def instantiate(self, config_xact):
@@ -2486,7 +2518,7 @@
     def create_msg(self):
         """ The network serice record as a message """
         nsr_dict = {"ns_instance_config_ref": self.id}
-        nsr = RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr.from_dict(nsr_dict)
+        nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr.from_dict(nsr_dict)
         #nsr.cloud_account = self.cloud_account_name
         nsr.sdn_account = self._sdn_account_name
         nsr.name_ref = self.name
@@ -2500,7 +2532,7 @@
         nsr.uptime = int(time.time()) - self._create_time
 
         for cfg_prim in self.nsd_msg.service_primitive:
-            cfg_prim = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_ServicePrimitive.from_dict(
+            cfg_prim = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_ServicePrimitive.from_dict(
                     cfg_prim.as_dict())
             nsr.service_primitive.append(cfg_prim)
 
@@ -2640,7 +2672,7 @@
     This class is responsible for substituting input parameters into an NSD.
     """
 
-    def __init__(self, log):
+    def __init__(self, log, project):
         """Create an instance of InputParameterSubstitution
 
         Arguments:
@@ -2648,6 +2680,7 @@
 
         """
         self.log = log
+        self.project = project
 
     def __call__(self, nsd, nsr_config):
         """Substitutes input parameters from the NSR config into the NSD
@@ -2667,7 +2700,7 @@
         # to be modified
         optional_input_parameters = set()
         for input_parameter in nsd.input_parameter_xpath:
-            optional_input_parameters.add(input_parameter.xpath)
+            optional_input_parameters.add(self.project.add_project(input_parameter.xpath))
 
         # Apply the input parameters to the descriptor
         if nsr_config.input_parameter:
@@ -2746,7 +2779,9 @@
     @staticmethod
     def path_for_id(nsd_id):
         """ Return path for the passed nsd_id"""
-        return "C,/nsd:nsd-catalog/nsd:nsd[nsd:id = '{}'".format(nsd_id)
+        return self._nsm._project.add_project(
+            "C,/nsd:nsd-catalog/nsd:nsd[nsd:id = '{}'".
+            format(nsd_id))
 
     def path(self):
         """ Return the message associated with this NetworkServiceDescriptor"""
@@ -2768,6 +2803,7 @@
         self._nsm = nsm
 
         self._regh = None
+        self._project = nsm._project
 
     @property
     def regh(self):
@@ -2778,6 +2814,11 @@
     def register(self):
         """ Register for Nsd create/update/delete/read requests from dts """
 
+        if self._regh:
+            self._log.warning("DTS handler already registered for project {}".
+                              format(self._project.name))
+            return
+
         def on_apply(dts, acg, xact, action, scratch):
             """Apply the  configuration"""
             is_recovery = xact.xact is None and action == rwdts.AppconfAction.INSTALL
@@ -2805,7 +2846,7 @@
             except Exception as e:
                 self._log.error("Exception in cleaning up NSD libs {}: {}".
                                 format(nsd_id, e))
-                self._log.excpetion(e)
+                self._log.exception(e)
 
         @asyncio.coroutine
         def on_prepare(dts, acg, xact, xact_info, ks_path, msg, scratch):
@@ -2845,10 +2886,17 @@
             # Need a list in scratch to store NSDs to create/update later
             # acg._scratch['nsds'] = list()
             self._regh = acg.register(
-                xpath=NsdDtsHandler.XPATH,
+                xpath=self._project.add_project(NsdDtsHandler.XPATH),
                 flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE,
                 on_prepare=on_prepare)
 
+    def deregister(self):
+        self._log.debug("De-register NSD handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
 
 class VnfdDtsHandler(object):
     """ DTS handler for VNFD config changes """
@@ -2860,6 +2908,7 @@
         self._loop = loop
         self._nsm = nsm
         self._regh = None
+        self._project = nsm._project
 
     @property
     def regh(self):
@@ -2870,6 +2919,11 @@
     def register(self):
         """ Register for VNFD configuration"""
 
+        if self._regh:
+            self._log.warning("DTS handler already registered for project {}".
+                              format(self._project.name))
+            return
+
         @asyncio.coroutine
         def on_apply(dts, acg, xact, action, scratch):
             """Apply the  configuration"""
@@ -2910,20 +2964,28 @@
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
+        xpath = self._project.add_project(VnfdDtsHandler.XPATH)
         self._log.debug(
-            "Registering for VNFD config using xpath: %s",
-            VnfdDtsHandler.XPATH,
-            )
+            "Registering for VNFD config using xpath {} for project {}"
+            .format(xpath, self._project))
         acg_hdl = rift.tasklets.AppConfGroup.Handler(on_apply=on_apply)
         with self._dts.appconf_group_create(handler=acg_hdl) as acg:
             # Need a list in scratch to store VNFDs to create/update later
             # acg._scratch['vnfds'] = list()
             # acg._scratch['deleted_vnfds'] = list()
             self._regh = acg.register(
-                xpath=VnfdDtsHandler.XPATH,
+                xpath=xpath,
                 flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
                 on_prepare=on_prepare)
 
+    def deregister(self):
+        self._log.debug("De-register VNFD handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
+
 class NsrRpcDtsHandler(object):
     """ The network service instantiation RPC DTS handler """
     EXEC_NSR_CONF_XPATH = "I,/nsr:start-network-service"
@@ -2945,7 +3007,9 @@
         self._ns_regh = None
 
         self._manager = None
-        self._nsr_config_url = NsrRpcDtsHandler.REST_BASE_V2_URL + 'config/ns-instance-config'
+        self._nsr_config_url = NsrRpcDtsHandler.REST_BASE_V2_URL + \
+                               'config/project/{}/ns-instance-config'. \
+                               format(self._nsm._project.name)
 
         self._model = RwYang.Model.create_libncx()
         self._model.load_schema_ypbc(RwNsrYang.get_schema())
@@ -2993,24 +3057,39 @@
 
     def _apply_ns_instance_config(self,payload_dict):
         #self._log.debug("At apply NS instance config with payload %s",payload_dict)
-        req_hdr= {'accept':'application/vnd.yang.data+json','content-type':'application/vnd.yang.data+json'}
-        response=requests.post(self._nsr_config_url, headers=req_hdr, auth=('admin', 'admin'),data=payload_dict,verify=False)
+        req_hdr= {'accept':'application/vnd.yang.data+json',
+                  'content-type':'application/vnd.yang.data+json'}
+        response=requests.post(self._nsr_config_url, headers=req_hdr,
+                               auth=('admin', 'admin'),data=payload_dict,verify=False)
         return response
 
     @asyncio.coroutine
     def register(self):
         """ Register for NS monitoring read from dts """
+        if self._ns_regh:
+            self._log.warning("RPC already registered for project {}".
+                              format(self._project.name))
+            return
+
         @asyncio.coroutine
         def on_ns_config_prepare(xact_info, action, ks_path, msg):
             """ prepare callback from dts start-network-service"""
             assert action == rwdts.QueryAction.RPC
             rpc_ip = msg
-            rpc_op = NsrYang.YangOutput_Nsr_StartNetworkService.from_dict({
-                    "nsr_id":str(uuid.uuid4())
-                })
 
-            if not ('name' in rpc_ip and  'nsd_ref' in rpc_ip and ('cloud_account' in rpc_ip or 'om_datacenter' in rpc_ip)):
-                self._log.error("Mandatory parameters name or nsd_ref or cloud account not found in start-network-service {}".format(rpc_ip))
+            if not self._nsm._project.rpc_check(msg, xact_info=xact_info):
+                return
+
+            rpc_op = NsrYang.YangOutput_Nsr_StartNetworkService.from_dict({
+                "nsr_id":str(uuid.uuid4()),
+                "project_name": msg.prject_name,
+            })
+
+            if not ('name' in rpc_ip and  'nsd_ref' in rpc_ip and
+                    ('cloud_account' in rpc_ip or 'om_datacenter' in rpc_ip)):
+                self._log.error("Mandatory parameters name or nsd_ref or " +
+                                "cloud account not found in start-network-service {}".
+                                format(rpc_ip))
 
 
             self._log.debug("start-network-service RPC input: {}".format(rpc_ip))
@@ -3029,11 +3108,11 @@
 
                 ns_instance_config_dict = {"id":rpc_op.nsr_id, "admin_status":"ENABLED"}
                 ns_instance_config_copy_dict = {k:v for k, v in rpc_ip.as_dict().items()
-                                                if k in RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr().fields}
+                                                if k in RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr().fields}
                 ns_instance_config_dict.update(ns_instance_config_copy_dict)
 
-                ns_instance_config = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr.from_dict(ns_instance_config_dict)
-                ns_instance_config.nsd = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_Nsd()
+                ns_instance_config = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr.from_dict(ns_instance_config_dict)
+                ns_instance_config.nsd = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_Nsd()
                 ns_instance_config.nsd.from_dict(nsd_copy.msg.as_dict())
 
                 payload_dict = ns_instance_config.to_json(self._model)
@@ -3076,6 +3155,13 @@
                                            flags=rwdts.Flag.PUBLISHER,
                                           )
 
+    def deregister(self):
+        self._log.debug("De-register NSR RPC for project {}".
+                        format(self._nsm._project.name))
+        if self._ns_regh:
+            self._ns_regh.deregister()
+            self._ns_regh = None
+
 
 class NsrDtsHandler(object):
     """ The network service DTS handler """
@@ -3088,6 +3174,7 @@
         self._log = log
         self._loop = loop
         self._nsm = nsm
+        self._project = self._nsm._project
 
         self._nsr_regh = None
         self._scale_regh = None
@@ -3102,13 +3189,18 @@
     def register(self):
         """ Register for Nsr create/update/delete/read requests from dts """
 
+        if self._nsr_regh:
+            self._log.warning("DTS handler already registered for project {}".
+                              format(self._project.name))
+            return
+
         def nsr_id_from_keyspec(ks):
-            nsr_path_entry = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr.schema().keyspec_to_entry(ks)
+            nsr_path_entry = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr.schema().keyspec_to_entry(ks)
             nsr_id = nsr_path_entry.key00.id
             return nsr_id
 
         def group_name_from_keyspec(ks):
-            group_path_entry = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup.schema().keyspec_to_entry(ks)
+            group_path_entry = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup.schema().keyspec_to_entry(ks)
             group_name = group_path_entry.key00.scaling_group_name_ref
             return group_name
 
@@ -3199,32 +3291,6 @@
             for vld in vl_delta["deleted"]:
                 yield from self._nsm.nsr_terminate_vl(nsr_id, vld)
 
-        def get_add_delete_update_cfgs(dts_member_reg, xact, key_name, scratch):
-            # Unfortunately, it is currently difficult to figure out what has exactly
-            # changed in this xact without Pbdelta support (RIFT-4916)
-            # As a workaround, we can fetch the pre and post xact elements and
-            # perform a comparison to figure out adds/deletes/updates
-            xact_cfgs = list(dts_member_reg.get_xact_elements(xact))
-            curr_cfgs = list(dts_member_reg.elements)
-
-            xact_key_map = {getattr(cfg, key_name): cfg for cfg in xact_cfgs}
-            curr_key_map = {getattr(cfg, key_name): cfg for cfg in curr_cfgs}
-
-            # Find Adds
-            added_keys = set(xact_key_map) - set(curr_key_map)
-            added_cfgs = [xact_key_map[key] for key in added_keys]
-
-            # Find Deletes
-            deleted_keys = set(curr_key_map) - set(xact_key_map)
-            deleted_cfgs = [curr_key_map[key] for key in deleted_keys]
-
-            # Find Updates
-            updated_keys = set(curr_key_map) & set(xact_key_map)
-            updated_cfgs = [xact_key_map[key] for key in updated_keys
-                            if xact_key_map[key] != curr_key_map[key]]
-
-            return added_cfgs, deleted_cfgs, updated_cfgs
-
         def get_nsr_key_pairs(dts_member_reg, xact):
             key_pairs = {}
             for instance_cfg, keyspec in dts_member_reg.get_xact_elements(xact, include_keyspec=True):
@@ -3273,7 +3339,11 @@
             def begin_instantiation(nsr):
                 # Begin instantiation
                 self._log.info("Beginning NS instantiation: %s", nsr.id)
-                yield from self._nsm.instantiate_ns(nsr.id, xact)
+                try:
+                    yield from self._nsm.instantiate_ns(nsr.id, xact)
+                except Exception as e:
+                    self._log.exception("NS instantiation: {}".format(e))
+                    raise e
 
             self._log.debug("Got nsr apply (xact: %s) (action: %s)(scr: %s)",
                             xact, action, scratch)
@@ -3289,8 +3359,7 @@
 
             (added_msgs, deleted_msgs, updated_msgs) = get_add_delete_update_cfgs(self._nsr_regh,
                                                                                   xact,
-                                                                                  "id",
-                                                                                  scratch)
+                                                                                  "id")
             self._log.debug("Added: %s, Deleted: %s, Updated: %s", added_msgs,
                             deleted_msgs, updated_msgs)
 
@@ -3401,24 +3470,40 @@
             acg.handle.prepare_complete_ok(xact_info.handle)
 
 
-        self._log.debug("Registering for NSR config using xpath: %s",
-                        NsrDtsHandler.NSR_XPATH)
+        xpath = self._project.add_project(NsrDtsHandler.NSR_XPATH)
+        self._log.debug("Registering for NSR config using xpath: {}".
+                        format(xpath))
 
         acg_hdl = rift.tasklets.AppConfGroup.Handler(on_apply=on_apply)
         with self._dts.appconf_group_create(handler=acg_hdl) as acg:
-            self._nsr_regh = acg.register(xpath=NsrDtsHandler.NSR_XPATH,
-                                      flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE,
-                                      on_prepare=on_prepare)
+            self._nsr_regh = acg.register(
+                xpath=xpath,
+                flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE,
+                on_prepare=on_prepare
+            )
 
             self._scale_regh = acg.register(
-                                      xpath=NsrDtsHandler.SCALE_INSTANCE_XPATH,
-                                      flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY| rwdts.Flag.CACHE,
-                                      )
+                xpath=self._project.add_project(NsrDtsHandler.SCALE_INSTANCE_XPATH),
+                flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY| rwdts.Flag.CACHE,
+            )
 
             self._key_pair_regh = acg.register(
-                                      xpath=NsrDtsHandler.KEY_PAIR_XPATH,
-                                      flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE,
-                                       )
+                xpath=self._project.add_project(NsrDtsHandler.KEY_PAIR_XPATH),
+                flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE,
+            )
+
+    def deregister(self):
+        self._log.debug("De-register NSR config for project {}".
+                        format(self._project.name))
+        if self._nsr_regh:
+            self._nsr_regh.deregister()
+            self._nsr_regh = None
+        if self._scale_regh:
+            self._scale_regh.deregister()
+            self._scale_regh = None
+        if self._key_pair_regh:
+            self._key_pair_regh.deregister()
+            self._key_pair_regh = None
 
 
 class NsrOpDataDtsHandler(object):
@@ -3430,6 +3515,8 @@
         self._log = log
         self._loop = loop
         self._nsm = nsm
+
+        self._project = nsm._project
         self._regh = None
 
     @property
@@ -3445,39 +3532,55 @@
     @asyncio.coroutine
     def register(self):
         """ Register for Nsr op data publisher registration"""
-        self._log.debug("Registering Nsr op data path %s as publisher",
-                        NsrOpDataDtsHandler.XPATH)
+        if self._regh:
+            self._log.warning("NSR op data handler already registered for project {}".
+                              format(self._project.name))
+            return
+
+        xpath = self._project.add_project(NsrOpDataDtsHandler.XPATH)
+        self._log.debug("Registering Nsr op data path {} as publisher".
+                        format(xpath))
 
         hdl = rift.tasklets.DTS.RegistrationHandler()
         handlers = rift.tasklets.Group.Handler()
         with self._dts.group_create(handler=handlers) as group:
-            self._regh = group.register(xpath=NsrOpDataDtsHandler.XPATH,
+            self._regh = group.register(xpath=xpath,
                                         handler=hdl,
                                         flags=rwdts.Flag.PUBLISHER | rwdts.Flag.NO_PREP_READ | rwdts.Flag.DATASTORE)
 
+    def deregister(self):
+        self._log.debug("De-register NSR opdata for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
-    def create(self, path, msg):
+    def create(self, xpath, msg):
         """
         Create an NS record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Creating NSR %s:%s", path, msg)
         self.regh.create_element(path, msg)
         self._log.debug("Created NSR, %s:%s", path, msg)
 
     @asyncio.coroutine
-    def update(self, path, msg, flags=rwdts.XactFlag.REPLACE):
+    def update(self, xpath, msg, flags=rwdts.XactFlag.REPLACE):
         """
         Update an NS record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Updating NSR, %s:%s regh = %s", path, msg, self.regh)
         self.regh.update_element(path, msg, flags)
         self._log.debug("Updated NSR, %s:%s", path, msg)
 
     @asyncio.coroutine
-    def delete(self, path):
+    def delete(self, xpath):
         """
         Update an NS record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Deleting NSR path:%s", path)
         self.regh.delete_element(path)
         self._log.debug("Deleted NSR path:%s", path)
@@ -3508,6 +3611,11 @@
     @asyncio.coroutine
     def register(self):
         """ Register for vnfr create/update/delete/ advises from dts """
+        if self._regh:
+            self._log.warning("VNFR DTS handler already registered for project {}".
+                              format(self._project.name))
+            return
+
 
         def on_commit(xact_info):
             """ The transaction has been committed """
@@ -3523,16 +3631,17 @@
                 xact_info, action, ks_path, msg
                 )
 
-            schema = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.schema()
+            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:
-                self._log.error("%s request for non existent record path %s",
-                                action, xpath)
+                # 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",
+                                    action, xpath)
                 xact_info.respond_xpath(rwdts.XactRspCode.NA, xpath)
 
                 return
 
-                self._log.debug("Deleting VNFR with id %s", path_entry.key00.id)
             if action == rwdts.QueryAction.CREATE or action == rwdts.QueryAction.UPDATE:
                 yield from self._nsm.update_vnfr(msg)
             elif action == rwdts.QueryAction.DELETE:
@@ -3547,10 +3656,17 @@
         hdl = rift.tasklets.DTS.RegistrationHandler(on_commit=on_commit,
                                                     on_prepare=on_prepare,)
         with self._dts.group_create() as group:
-            self._regh = group.register(xpath=VnfrDtsHandler.XPATH,
+            self._regh = group.register(xpath=self._nsm._project.add_project(
+                VnfrDtsHandler.XPATH),
                                         handler=hdl,
                                         flags=(rwdts.Flag.SUBSCRIBER),)
 
+    def deregister(self):
+        self._log.debug("De-register VNFR for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
 
 class NsdRefCountDtsHandler(object):
     """ The NSD Ref Count DTS handler """
@@ -3577,6 +3693,11 @@
     @asyncio.coroutine
     def register(self):
         """ Register for NSD ref count read from dts """
+        if self._regh:
+            self._log.warning("NSD ref DTS handler already registered for project {}".
+                              format(self._project.name))
+            return
+
 
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
@@ -3584,7 +3705,7 @@
             xpath = ks_path.to_xpath(RwNsrYang.get_schema())
 
             if action == rwdts.QueryAction.READ:
-                schema = RwNsrYang.YangData_Nsr_NsInstanceOpdata_NsdRefCount.schema()
+                schema = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_NsdRefCount.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
                 nsd_list = yield from self._nsm.get_nsd_refcount(path_entry.key00.nsd_id_ref)
                 for xpath, msg in nsd_list:
@@ -3597,19 +3718,28 @@
 
         hdl = rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare,)
         with self._dts.group_create() as group:
-            self._regh = group.register(xpath=NsdRefCountDtsHandler.XPATH,
+            self._regh = group.register(xpath=self._nsm._project.add_project(
+                NsdRefCountDtsHandler.XPATH),
                                         handler=hdl,
                                         flags=rwdts.Flag.PUBLISHER,)
 
+    def deregister(self):
+        self._log.debug("De-register NSD Ref count for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
 
 class NsManager(object):
     """ The Network Service Manager class"""
-    def __init__(self, dts, log, loop,
+    def __init__(self, dts, log, loop, project,
                  nsr_handler, vnfr_handler, vlr_handler, ro_plugin_selector,
                  vnffgmgr, vnfd_pub_handler, cloud_account_handler):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._nsr_handler = nsr_handler
         self._vnfr_pub_handler = vnfr_handler
         self._vlr_pub_handler = vlr_handler
@@ -3640,8 +3770,9 @@
                               VnfrDtsHandler(dts, log, loop, self),
                               NsdRefCountDtsHandler(dts, log, loop, self),
                               NsrDtsHandler(dts, log, loop, self),
-                              ScalingRpcHandler(log, dts, loop, self.scale_rpc_callback),
-                              NsrRpcDtsHandler(dts,log,loop,self),
+                              ScalingRpcHandler(log, dts, loop, self._project,
+                                                self.scale_rpc_callback),
+                              NsrRpcDtsHandler(dts, log, loop, self),
                               self._vnfd_dts_handler,
                               self.cfgmgr_obj,
                               ]
@@ -3717,6 +3848,11 @@
         for dts_handle in self._dts_handlers:
             yield from dts_handle.register()
 
+    def deregister(self):
+        """ Register all static DTS handlers """
+        for dts_handle in self._dts_handlers:
+            yield from dts_handle.deregister()
+
 
     def get_ns_by_nsr_id(self, nsr_id):
         """ get NSR by nsr id """
@@ -3756,12 +3892,16 @@
             msg : RPC input
             action : Scaling Action
         """
-        ScalingGroupInstance = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup_Instance
-        ScalingGroup = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup
+        ScalingGroupInstance = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup_Instance
+        ScalingGroup = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup
 
-        xpath = ('C,/nsr:ns-instance-config/nsr:nsr[nsr:id="{}"]').format(
-                          msg.nsr_id_ref)
-        instance = ScalingGroupInstance.from_dict({"id": msg.instance_id})
+        xpath = self._project.add_project(
+            ('C,/nsr:ns-instance-config/nsr:nsr[nsr:id="{}"]').
+            format(msg.nsr_id_ref))
+
+        instance = ScalingGroupInstance.from_dict({
+            "id": msg.instance_id,
+            "project_name": self._project.name,})
 
         @asyncio.coroutine
         def get_nsr_scaling_group():
@@ -3861,6 +4001,7 @@
                                    nsr_msg,
                                    sdn_account_name,
                                    key_pairs,
+                                   self._project,
                                    restart_mode=restart_mode,
                                    vlr_handler=self._ro_plugin_selector._records_publisher._vlr_pub_hdlr
                                    )
@@ -3919,7 +4060,7 @@
 
     @asyncio.coroutine
     def get_nsr_config(self, nsd_id):
-        xpath = "C,/nsr:ns-instance-config"
+        xpath = self._project.add_project("C,/nsr:ns-instance-config")
         results = yield from self._dts.query_read(xpath, rwdts.XactFlag.MERGE)
 
         for result in results:
@@ -4098,18 +4239,18 @@
 
         def nsd_refcount_xpath(nsd_id):
             """ xpath for ref count entry """
-            return (NsdRefCountDtsHandler.XPATH +
+            return (self._project.add_project(NsdRefCountDtsHandler.XPATH) +
                     "[rw-nsr:nsd-id-ref = '{}']").format(nsd_id)
 
         nsd_list = []
         if nsd_id is None or nsd_id == "":
             for nsd in self._nsds.values():
-                nsd_msg = RwNsrYang.YangData_Nsr_NsInstanceOpdata_NsdRefCount()
+                nsd_msg = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_NsdRefCount()
                 nsd_msg.nsd_id_ref = nsd.id
                 nsd_msg.instance_ref_count = nsd.ref_count
                 nsd_list.append((nsd_refcount_xpath(nsd.id), nsd_msg))
         elif nsd_id in self._nsds:
-            nsd_msg = RwNsrYang.YangData_Nsr_NsInstanceOpdata_NsdRefCount()
+            nsd_msg = RwNsrYang.YangData_RwProject_Project_NsInstanceOpdata_NsdRefCount()
             nsd_msg.nsd_id_ref = self._nsds[nsd_id].id
             nsd_msg.instance_ref_count = self._nsds[nsd_id].ref_count
             nsd_list.append((nsd_refcount_xpath(nsd_id), nsd_msg))
@@ -4145,10 +4286,12 @@
     """ This class provides a publisher interface that allows plugin objects
         to publish NSR/VNFR/VLR"""
 
-    def __init__(self, dts, log, loop, nsr_pub_hdlr, vnfr_pub_hdlr, vlr_pub_hdlr):
+    def __init__(self, dts, log, loop, project, nsr_pub_hdlr,
+                 vnfr_pub_hdlr, vlr_pub_hdlr,):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._nsr_pub_hdlr = nsr_pub_hdlr
         self._vlr_pub_hdlr = vlr_pub_hdlr
         self._vnfr_pub_hdlr = vnfr_pub_hdlr
@@ -4180,13 +4323,13 @@
     @asyncio.coroutine
     def publish_vlr(self, xact, vlr):
         """ Publish a VLR """
-        path = VirtualLinkRecord.vlr_xpath(vlr)
+        path = self._project.add_project(VirtualLinkRecord.vlr_xpath(vlr))
         return (yield from self._vlr_pub_hdlr.update(xact, path, vlr))
 
     @asyncio.coroutine
     def unpublish_vlr(self, xact, vlr):
         """ Unpublish a VLR """
-        path = VirtualLinkRecord.vlr_xpath(vlr)
+        path = self._project.add_project(VirtualLinkRecord.vlr_xpath(vlr))
         return (yield from self._vlr_pub_hdlr.delete(xact, path))
 
 
@@ -4200,24 +4343,35 @@
 
     ACTION = Enum('ACTION', 'SCALE_IN SCALE_OUT')
 
-    def __init__(self, log, dts, loop, callback=None):
-        super().__init__(log, dts, loop)
+    def __init__(self, log, dts, loop, project, callback=None):
+        super().__init__(log, dts, loop, project)
         self.callback = callback
         self.last_instance_id = defaultdict(int)
+        self._regh_in = None
+        self._regh_out = None
 
     @asyncio.coroutine
     def register(self):
 
+        if self._regh_in:
+            self._log.warning("RPC already registered for project {}".
+                              format(self._project.name))
+            return
+
         @asyncio.coroutine
         def on_scale_in_prepare(xact_info, action, ks_path, msg):
             assert action == rwdts.QueryAction.RPC
 
             try:
+                if not self._project.rpc_check(msg, xact_info=xact_info):
+                    return
+
                 if self.callback:
                     self.callback(xact_info.xact, msg, self.ACTION.SCALE_IN)
 
                 rpc_op = NsrYang.YangOutput_Nsr_ExecScaleIn.from_dict({
-                      "instance_id": msg.instance_id})
+                    "instance_id": msg.instance_id,
+                    "project_name": self._project.name,})
 
                 xact_info.respond_xpath(
                     rwdts.XactRspCode.ACK,
@@ -4235,6 +4389,9 @@
             assert action == rwdts.QueryAction.RPC
 
             try:
+                if not self._project.rpc_check(msg, xact_info=xact_info):
+                    return
+
                 scaling_group = msg.scaling_group_name_ref
                 if not msg.instance_id:
                     last_instance_id = self.last_instance_id[scale_group]
@@ -4245,7 +4402,8 @@
                     self.callback(xact_info.xact, msg, self.ACTION.SCALE_OUT)
 
                 rpc_op = NsrYang.YangOutput_Nsr_ExecScaleOut.from_dict({
-                      "instance_id": msg.instance_id})
+                    "instance_id": msg.instance_id,
+                    "project_name": self._project.name,})
 
                 xact_info.respond_xpath(
                     rwdts.XactRspCode.ACK,
@@ -4264,14 +4422,122 @@
               on_prepare=on_scale_out_prepare)
 
         with self.dts.group_create() as group:
-            group.register(
-                  xpath=self.__class__.SCALE_IN_INPUT_XPATH,
-                  handler=scale_in_hdl,
-                  flags=rwdts.Flag.PUBLISHER)
-            group.register(
-                  xpath=self.__class__.SCALE_OUT_INPUT_XPATH,
-                  handler=scale_out_hdl,
-                  flags=rwdts.Flag.PUBLISHER)
+            self._regh_in = group.register(
+                xpath=self.__class__.SCALE_IN_INPUT_XPATH,
+                handler=scale_in_hdl,
+                flags=rwdts.Flag.PUBLISHER)
+            self._regh_out = group.register(
+                xpath=self.__class__.SCALE_OUT_INPUT_XPATH,
+                handler=scale_out_hdl,
+                flags=rwdts.Flag.PUBLISHER)
+
+    def deregister(self):
+        self._log.debug("De-register scale RPCs for project {}".
+                        format(self._project.name))
+        if self._regh_in:
+            self._regh_in.deregister()
+            self._regh_in = None
+        if self._regh_out:
+            self._regh_out.deregister()
+            self._regh_out = None
+
+
+class NsmProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(NsmProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self._nsm = None
+
+        self._ro_plugin_selector = None
+        self._vnffgmgr = None
+
+        self._nsr_pub_handler = None
+        self._vnfr_pub_handler = None
+        self._vlr_pub_handler = None
+        self._vnfd_pub_handler = None
+        self._scale_cfg_handler = None
+
+        self._records_publisher_proxy = None
+
+    @asyncio.coroutine
+    def register(self):
+        self._nsr_pub_handler = publisher.NsrOpDataDtsHandler(
+            self._dts, self.log, self.loop, self)
+        yield from self._nsr_pub_handler.register()
+
+        self._vnfr_pub_handler = publisher.VnfrPublisherDtsHandler(
+            self._dts, self.log, self.loop, self)
+        yield from self._vnfr_pub_handler.register()
+
+        self._vlr_pub_handler = publisher.VlrPublisherDtsHandler(
+            self._dts, self.log, self.loop, self)
+        yield from self._vlr_pub_handler.register()
+
+        manifest = self._tasklet.tasklet_info.get_pb_manifest()
+        use_ssl = manifest.bootstrap_phase.rwsecurity.use_ssl
+        ssl_cert = manifest.bootstrap_phase.rwsecurity.cert
+        ssl_key = manifest.bootstrap_phase.rwsecurity.key
+
+        self._vnfd_pub_handler = publisher.VnfdPublisher(
+            use_ssl, ssl_cert, ssl_key, self.loop, self)
+
+        self._records_publisher_proxy = NsmRecordsPublisherProxy(
+                self._dts,
+                self.log,
+                self.loop,
+                self,
+                self._nsr_pub_handler,
+                self._vnfr_pub_handler,
+                self._vlr_pub_handler,
+                )
+
+        # Register the NSM to receive the nsm plugin
+        # when cloud account is configured
+        self._ro_plugin_selector = cloud.ROAccountPluginSelector(
+                self._dts,
+                self.log,
+                self.loop,
+                self,
+                self._records_publisher_proxy,
+                )
+        yield from self._ro_plugin_selector.register()
+
+        self._cloud_account_handler = cloud.CloudAccountConfigSubscriber(
+                self._log,
+                self._dts,
+                self.log_hdl,
+                self,
+                )
+
+        yield from self._cloud_account_handler.register()
+
+        self._vnffgmgr = rwvnffgmgr.VnffgMgr(self._dts, self.log, self.log_hdl, self.loop, self)
+        yield from self._vnffgmgr.register()
+
+        self._nsm = NsManager(
+                self._dts,
+                self.log,
+                self.loop,
+                self,
+                self._nsr_pub_handler,
+                self._vnfr_pub_handler,
+                self._vlr_pub_handler,
+                self._ro_plugin_selector,
+                self._vnffgmgr,
+                self._vnfd_pub_handler,
+                self._cloud_account_handler,
+                )
+
+        yield from self._nsm.register()
+
+    def deregister(self):
+        self._log.debug("Project {} de-register".format(self.name))
+        self._nsm.deregister()
+        self._vnffgmgr.deregister()
+        self._cloud_account_handler.deregister()
+        self._ro_plugin_selector.deregister()
 
 
 class NsmTasklet(rift.tasklets.Tasklet):
@@ -4284,18 +4550,12 @@
         self.rwlog.set_subcategory("nsm")
 
         self._dts = None
-        self._nsm = None
+        self.project_handler = None
+        self.projects = {}
 
-        self._ro_plugin_selector = None
-        self._vnffgmgr = None
-
-        self._nsr_handler = None
-        self._vnfr_pub_handler = None
-        self._vlr_pub_handler = None
-        self._vnfd_pub_handler = None
-        self._scale_cfg_handler = None
-
-        self._records_publisher_proxy = None
+    @property
+    def dts(self):
+        return self._dts
 
     def start(self):
         """ The task start callback """
@@ -4326,67 +4586,11 @@
         """ Task init callback """
         self.log.debug("Got instance started callback")
 
-        self.log.debug("creating config account handler")
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, NsmProject)
+        self.project_handler.register()
 
-        self._nsr_pub_handler = publisher.NsrOpDataDtsHandler(self._dts, self.log, self.loop)
-        yield from self._nsr_pub_handler.register()
 
-        self._vnfr_pub_handler = publisher.VnfrPublisherDtsHandler(self._dts, self.log, self.loop)
-        yield from self._vnfr_pub_handler.register()
-
-        self._vlr_pub_handler = publisher.VlrPublisherDtsHandler(self._dts, self.log, self.loop)
-        yield from self._vlr_pub_handler.register()
-
-        manifest = self.tasklet_info.get_pb_manifest()
-        use_ssl = manifest.bootstrap_phase.rwsecurity.use_ssl
-        ssl_cert = manifest.bootstrap_phase.rwsecurity.cert
-        ssl_key = manifest.bootstrap_phase.rwsecurity.key
-
-        self._vnfd_pub_handler = publisher.VnfdPublisher(use_ssl, ssl_cert, ssl_key, self.loop)
-
-        self._records_publisher_proxy = NsmRecordsPublisherProxy(
-                self._dts,
-                self.log,
-                self.loop,
-                self._nsr_pub_handler,
-                self._vnfr_pub_handler,
-                self._vlr_pub_handler,
-                )
-
-        # Register the NSM to receive the nsm plugin
-        # when cloud account is configured
-        self._ro_plugin_selector = cloud.ROAccountPluginSelector(
-                self._dts,
-                self.log,
-                self.loop,
-                self._records_publisher_proxy,
-                )
-        yield from self._ro_plugin_selector.register()
-
-        self._cloud_account_handler = cloud.CloudAccountConfigSubscriber(
-                self._log,
-                self._dts,
-                self.log_hdl)
-
-        yield from self._cloud_account_handler.register()
-
-        self._vnffgmgr = rwvnffgmgr.VnffgMgr(self._dts, self.log, self.log_hdl, self.loop)
-        yield from self._vnffgmgr.register()
-
-        self._nsm = NsManager(
-                self._dts,
-                self.log,
-                self.loop,
-                self._nsr_pub_handler,
-                self._vnfr_pub_handler,
-                self._vlr_pub_handler,
-                self._ro_plugin_selector,
-                self._vnffgmgr,
-                self._vnfd_pub_handler,
-                self._cloud_account_handler
-                )
-
-        yield from self._nsm.register()
 
     @asyncio.coroutine
     def run(self):
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwvnffgmgr.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwvnffgmgr.py
index 1f4f4bc..81f22e9 100755
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwvnffgmgr.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwvnffgmgr.py
@@ -61,20 +61,26 @@
 
 class VnffgMgr(object):
     """ Implements the interface to backend plugins to fetch topology """
-    def __init__(self, dts, log, log_hdl, loop):
+    def __init__(self, dts, log, log_hdl, loop, project):
         self._account = {}
         self._dts = dts
         self._log = log
         self._log_hdl = log_hdl
         self._loop = loop
+        self._project = project
         self._sdn = {}
-        self._sdn_handler = SDNAccountDtsHandler(self._dts,self._log,self)
+        self._sdn_handler = SDNAccountDtsHandler(self._dts, self._log, self)
         self._vnffgr_list = {}
 
     @asyncio.coroutine
     def register(self):
         yield from self._sdn_handler.register()
 
+    def deregister(self):
+        self._log.debug("Project {} de-register vnffgmgr".
+                        format(self._project.name))
+        self._sdn_handler.deregister()
+
     def set_sdn_account(self,account):
         if (account.name in self._account):
             self._log.error("SDN Account is already set")
@@ -323,14 +329,16 @@
         del self._vnffgr_list[vnffgr_id]
 
 class SDNAccountDtsHandler(object):
-    XPATH = "C,/rw-project:project/rw-sdn:sdn/rw-sdn:account"
+    XPATH = "C,/rw-sdn:sdn/rw-sdn:account"
 
     def __init__(self, dts, log, parent):
         self._dts = dts
         self._log = log
         self._parent = parent
+        self._project = self._parent._project
 
         self._sdn_account = {}
+        self._reg = None
 
     def _set_sdn_account(self, account):
         self._log.info("Setting sdn account: {}".format(account))
@@ -380,9 +388,11 @@
                     if msg.has_field("account_type"):
                         errmsg = "Cannot update SDN account's account-type."
                         self._log.error(errmsg)
-                        xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
-                                                   SDNAccountDtsHandler.XPATH,
-                                                   errmsg)
+                        xact_info.send_error_xpath(
+                            RwTypes.RwStatus.FAILURE,
+                            self._project.add_project(SDNAccountDtsHandler.XPATH),
+                            errmsg
+                        )
                         raise SdnAccountError(errmsg)
 
                     # Update the sdn account record
@@ -392,9 +402,11 @@
                     if not msg.has_field('account_type'):
                         errmsg = "New SDN account must contain account-type field."
                         self._log.error(errmsg)
-                        xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
-                                                   SDNAccountDtsHandler.XPATH,
-                                                   errmsg)
+                        xact_info.send_error_xpath(
+                            RwTypes.RwStatus.FAILURE,
+                            self._project.add_project(SDNAccountDtsHandler.XPATH),
+                            errmsg
+                        )
                         raise SdnAccountError(errmsg)
 
                     # Set the sdn account record
@@ -403,20 +415,23 @@
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
 
-        self._log.debug("Registering for Sdn Account config using xpath: %s",
-                        SDNAccountDtsHandler.XPATH,
-                        )
+        xpath = self._project.add_project(SDNAccountDtsHandler.XPATH)
+        self._log.debug("Registering for Sdn Account config using xpath: {}".
+                        format(xpath))
 
         acg_handler = rift.tasklets.AppConfGroup.Handler(
                         on_apply=apply_config,
                         )
 
         with self._dts.appconf_group_create(acg_handler) as acg:
-            acg.register(
-                    xpath=SDNAccountDtsHandler.XPATH,
-                    flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
-                    on_prepare=on_prepare
-                    )
+            self._reg = acg.register(
+                xpath=xpath,
+                flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
+                on_prepare=on_prepare
+            )
 
-
-
+    def deregister(self):
+        self._log.debug("De-register SDN Account handler in vnffg for project".
+                        format(self._project.name))
+        self._reg.deregister()
+        self._reg = None
diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/scale_group.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/scale_group.py
index 8bbf894..e3b7f1f 100644
--- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/scale_group.py
+++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/scale_group.py
@@ -104,7 +104,7 @@
 
     def create_record_msg(self):
         """ Returns a NSR Scaling group record """
-        msg = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_ScalingGroupRecord(
+        msg = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_ScalingGroupRecord(
                 scaling_group_name_ref=self.name,
                 )
 
@@ -259,7 +259,7 @@
         return self._vnfrs.values()
 
     def create_record_msg(self):
-        msg = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_ScalingGroupRecord_Instance(
+        msg = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr_ScalingGroupRecord_Instance(
                 instance_id=self._instance_id,
                 create_time=self._create_time,
                 op_status=self._op_status,
diff --git a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/publisher/download_status.py b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/publisher/download_status.py
index 6890241..9c768a6 100644
--- a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/publisher/download_status.py
+++ b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/publisher/download_status.py
@@ -28,13 +28,14 @@
 
 class DownloadStatusPublisher(mano_dts.DtsHandler, url_downloader.DownloaderProtocol):
 
-    def __init__(self, log, dts, loop):
-        super().__init__(log, dts, loop)
+    def __init__(self, log, dts, loop, project):
+        super().__init__(log, dts, loop, project)
         self.tasks = {}
 
     def xpath(self, download_id=None):
-        return ("D,/rw-pkg-mgmt:download-jobs/rw-pkg-mgmt:job" +
-            ("[download-id='{}']".format(download_id) if download_id else ""))
+        return self._project.add_project("D,/rw-pkg-mgmt:download-jobs/rw-pkg-mgmt:job" +
+                                         ("[download-id='{}']".
+                                          format(download_id) if download_id else ""))
 
     @asyncio.coroutine
     def register(self):
@@ -43,6 +44,12 @@
 
         assert self.reg is not None
 
+    def dergister(self):
+        self._log.debug("De-registering download status for project {}".
+                        format(self.project.name))
+        if self.reg:
+            self.reg.deregister()
+            self.reg = None
 
     def on_download_progress(self, download_job_msg):
         """callback that triggers update.
diff --git a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rpc.py b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rpc.py
index f55a8fd..c207b43 100644
--- a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rpc.py
+++ b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rpc.py
@@ -102,22 +102,36 @@
     3. Return a tracking ID for the client to monitor the entire status
 
     """
-    def __init__(self, log, dts, loop, proxy, publisher):
+    def __init__(self, log, dts, loop, proxy, tasklet):
         """
         Args:
             proxy: Any impl of .proxy.AbstractPackageManagerProxy
-            publisher: Instance of DownloadStatusPublisher
+            publisher: Instance of tasklet to find the DownloadStatusPublisher
+                       for a specific project
         """
         super().__init__(log, dts, loop)
         self.proxy = proxy
-        self.publisher = publisher
+        self.tasklet = tasklet
 
     @property
     def xpath(self):
         return "/rw-pkg-mgmt:package-file-add"
 
+    def get_publisher(self, msg):
+        try:
+            proj = self.tasklet.projects[msg.project_name]
+        except Exception as e:
+            err = "Project or project name not found {}: {}". \
+                  format(msg.as_dict(), e)
+            self.log.error (err)
+            raise Exception (err)
+
+        return proj.job_handler
+
     @asyncio.coroutine
     def callback(self, ks_path, msg):
+        publisher = self.get_publisher(msg)
+
         if not msg.external_url:
             # For now we will only support External URL download
             raise Exception ("No download URL provided")
@@ -138,7 +152,7 @@
                 proxy=self.proxy,
                 log=self.log)
 
-        download_id = yield from self.publisher.register_downloader(url_downloader)
+        download_id = yield from publisher.register_downloader(url_downloader)
 
         rpc_op = RPC_PACKAGE_ADD_ENDPOINT.from_dict({"task_id": download_id})
 
diff --git a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rwpkgmgr.py b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rwpkgmgr.py
index d4e5736..18acc4d 100644
--- a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rwpkgmgr.py
+++ b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/rwpkgmgr.py
@@ -32,13 +32,33 @@
         RwDts as rwdts,
         RwPkgMgmtYang)
 import rift.tasklets
-
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+)
 
 from . import rpc
 from .proxy import filesystem
 from . import publisher as pkg_publisher
 
 
+class PackageManagerProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(PackageManagerProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self.job_handler = pkg_publisher.DownloadStatusPublisher(
+            self._log, self._dts, self._loop, self)
+
+    @asyncio.coroutine
+    def register (self):
+        yield from self.job_handler.register()
+
+    def deregister (self):
+        yield from self.job_handler.deregister()
+
+
 class PackageManagerTasklet(rift.tasklets.Tasklet):
     def __init__(self, *args, **kwargs):
         try:
@@ -46,6 +66,10 @@
             self.rwlog.set_category("rw-mano-log")
             self.endpoint_rpc = None
             self.schema_rpc = None
+
+            self._project_handler = None
+            self.projects = {}
+
         except Exception as e:
             self.log.exception(e)
 
@@ -64,14 +88,12 @@
         proxy = filesystem.FileSystemProxy(self.loop, self.log)
 
         args = [self.log, self.dts, self.loop]
-        self.job_handler = pkg_publisher.DownloadStatusPublisher(*args)
-
         args.append(proxy)
         self.endpoint_rpc = rpc.EndpointDiscoveryRpcHandler(*args)
         self.schema_rpc = rpc.SchemaRpcHandler(*args)
         self.delete_rpc = rpc.PackageDeleteOperationsRpcHandler(*args)
 
-        args.append(self.job_handler)
+        args.append(self)
         self.pkg_op = rpc.PackageOperationsRpcHandler(*args)
 
     def stop(self):
@@ -85,9 +107,12 @@
         yield from self.endpoint_rpc.register()
         yield from self.schema_rpc.register()
         yield from self.pkg_op.register()
-        yield from self.job_handler.register()
         yield from self.delete_rpc.register()
 
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, PackageManagerProject)
+        self.project_handler.register()
+
     @asyncio.coroutine
     def run(self):
         pass
diff --git a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/subscriber/download_status.py b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/subscriber/download_status.py
index c4a5a53..ea4b5e8 100644
--- a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/subscriber/download_status.py
+++ b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/subscriber/download_status.py
@@ -21,8 +21,9 @@
 
 
 class DownloadStatusSubscriber(mano_dts.AbstractOpdataSubscriber):
-    def __init__(self, log, dts, loop, callback=None):
-        super().__init__(log, dts, loop, callback)
+    def __init__(self, log, dts, loop, project, callback=None):
+        super().__init__(log, dts, loop, project, callback)
 
     def get_xpath(self):
-        return ("D,/rw-pkg-mgmt:download-jobs/rw-pkg-mgmt:job")
+        return self._project.add_project(
+            "D,/rw-pkg-mgmt:download-jobs/rw-pkg-mgmt:job")
diff --git a/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_config.py b/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_config.py
index 5035b18..1b1c9bf 100644
--- a/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_config.py
+++ b/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_config.py
@@ -1,6 +1,6 @@
 
-# 
-#   Copyright 2016 RIFT.IO Inc
+#
+#   Copyright 2016-2017 RIFT.IO Inc
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -51,12 +51,26 @@
         self._parent = parent
 
         self._cloud_sub = None
+        self._res_sub = None
+        self._project = parent._project
 
     @asyncio.coroutine
     def register(self):
         yield from self.register_resource_pool_operational_data()
         self.register_cloud_account_config()
 
+    def deregister(self):
+        self._log.debug("De-register for project {}".format(self._project.name))
+        if self._cloud_sub:
+            self._cloud_sub.deregister()
+            self._cloud_sub = None
+
+        if self._res_sub:
+            self._res_sub.delete_element(
+                self._project.add_project(ResourceMgrConfig.XPATH_POOL_OPER_DATA))
+            self._res_sub.deregister()
+            self._res_sub = None
+
     def register_cloud_account_config(self):
         def on_add_cloud_account_apply(account):
             self._log.debug("Received on_add_cloud_account: %s", account)
@@ -78,8 +92,9 @@
                 )
 
         self._cloud_sub = rift.mano.cloud.CloudAccountConfigSubscriber(
-                self._dts, self._log, self._rwlog_hdl, cloud_callbacks
-                )
+            self._dts, self._log, self._rwlog_hdl,
+            self._project, cloud_callbacks
+        )
         self._cloud_sub.register()
 
     @asyncio.coroutine
@@ -102,14 +117,14 @@
                     cloud_account_msg.records.append(pool_info)
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK,
-                                    ResourceMgrConfig.XPATH_POOL_OPER_DATA,
+                                    self._project.add_project(ResourceMgrConfig.XPATH_POOL_OPER_DATA),
                                     msg=msg,)
 
-        self._log.debug("Registering for Resource Mgr resource-pool-record using xpath: %s",
-                        ResourceMgrConfig.XPATH_POOL_OPER_DATA)
+        xpath = self._project.add_project(ResourceMgrConfig.XPATH_POOL_OPER_DATA)
+        self._log.debug("Registering for Resource Mgr resource-pool-record using xpath: {}".
+                        format(xpath))
 
         handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare)
-        response = yield from self._dts.register(xpath=ResourceMgrConfig.XPATH_POOL_OPER_DATA,
-                                                 handler=handler,
-                                                 flags=rwdts.Flag.PUBLISHER)
-
+        self._res_sub = yield from self._dts.register(xpath=xpath,
+                                                      handler=handler,
+                                                      flags=rwdts.Flag.PUBLISHER)
diff --git a/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_events.py b/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_events.py
index c80925c..360390b 100755
--- a/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_events.py
+++ b/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgr_events.py
@@ -48,6 +48,7 @@
         self._dts = dts
         self._loop = loop
         self._parent = parent
+        self._project = parent._project
         self._vdu_reg = None
         self._link_reg = None
 
@@ -60,22 +61,34 @@
         yield from asyncio.wait([self._link_reg_event.wait(), self._vdu_reg_event.wait()],
                                 timeout=timeout, loop=self._loop)
 
-    def create_record_dts(self, regh, xact, path, msg):
+    def _add_config_flag(self, xpath, config=False):
+        if xpath[0] == '/':
+            if config:
+                return 'C,' + xpath
+            else:
+                return 'D,' + xpath
+
+        return xpath
+
+    def create_record_dts(self, regh, xact, xpath, msg):
         """
         Create a record in DTS with path and message
         """
+        path = self._add_config_flag(self._project.add_project(xpath))
         self._log.debug("Creating Resource Record xact = %s, %s:%s",
                         xact, path, msg)
         regh.create_element(path, msg)
 
-    def delete_record_dts(self, regh, xact, path):
+    def delete_record_dts(self, regh, xact, xpath):
         """
         Delete a VNFR record in DTS with path and message
         """
+        path = self._add_config_flag(self._project.add_project(xpath))
         self._log.debug("Deleting Resource Record xact = %s, %s",
                         xact, path)
         regh.delete_element(path)
 
+
     @asyncio.coroutine
     def register(self):
         @asyncio.coroutine
@@ -161,12 +174,17 @@
                 yield from self._parent.release_virtual_network(pathentry.key00.event_id)
                 self.delete_record_dts(self._link_reg, None, ks_path.to_xpath(RwResourceMgrYang.get_schema()))
             elif action == rwdts.QueryAction.READ:
-                response_info = yield from self._parent.read_virtual_network_info(pathentry.key00.event_id)
+                # TODO: Check why we are getting null event id request
+                if pathentry.key00.event_id:
+                    response_info = yield from self._parent.read_virtual_network_info(pathentry.key00.event_id)
+                else:
+                    xact_info.respond_xpath(rwdts.XactRspCode.NA)
+                    return
             else:
                 raise ValueError("Only read/create/delete actions available. Received action: %s" %(action))
 
-            self._log.debug("Responding with VirtualLinkInfo at xpath %s: %s.",
-                            response_xpath, response_info)
+            self._log.info("Responding with VirtualLinkInfo at xpath %s: %s.",
+                           response_xpath, response_info)
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK, response_xpath, response_info)
 
@@ -177,7 +195,7 @@
             return rwdts.MemberRspCode.ACTION_OK
 
         def monitor_vdu_state(response_xpath, pathentry):
-            self._log.info("Initiating VDU state monitoring for xpath: %s ", response_xpath)
+            self._log.debug("Initiating VDU state monitoring for xpath: %s ", response_xpath)
             time_to_wait = 300
             sleep_time = 2
             loop_cnt = int(time_to_wait/sleep_time)
@@ -197,7 +215,8 @@
                                                       response_info)
                 else:
                     if response_info.resource_state == 'active' or response_info.resource_state == 'failed':
-                        self._log.info("VDU state monitoring: VDU reached terminal state. Publishing VDU info: %s at path: %s",
+                        self._log.info("VDU state monitoring: VDU reached terminal state. " +
+                                       "Publishing VDU info: %s at path: %s",
                                        response_info, response_xpath)
                         yield from self._dts.query_update(response_xpath,
                                                           rwdts.XactFlag.ADVISE,
@@ -205,7 +224,9 @@
                         return
             else:
                 ### End of loop. This is only possible if VDU did not reach active state
-                err_msg = "VDU state monitoring: VDU at xpath :{} did not reached active state in {} seconds. Aborting monitoring".format(response_xpath, time_to_wait)
+                err_msg = ("VDU state monitoring: VDU at xpath :{} did not reached active " +
+                           "state in {} seconds. Aborting monitoring".
+                           format(response_xpath, time_to_wait))
                 self._log.info(err_msg)
                 response_info = RwResourceMgrYang.VDUEventData_ResourceInfo()
                 response_info.resource_state = 'failed'
@@ -217,6 +238,7 @@
 
         def allocate_vdu_task(ks_path, event_id, cloud_account, request_msg):
             response_xpath = ks_path.to_xpath(RwResourceMgrYang.get_schema()) + "/resource-info"
+            response_xpath = self._add_config_flag(response_xpath)
             schema = RwResourceMgrYang.VDUEventData().schema()
             pathentry = schema.keyspec_to_entry(ks_path)
             try:
@@ -233,21 +255,22 @@
                                                   response_info)
             else:
                 if response_info.resource_state == 'failed' or response_info.resource_state == 'active' :
-                    self._log.info("Virtual compute create task completed. Publishing VDU info: %s at path: %s",
-                                   response_info, response_xpath)
+                    self._log.debug("Virtual compute create task completed. Publishing VDU info: %s at path: %s",
+                                    response_info, response_xpath)
                     yield from self._dts.query_update(response_xpath,
                                                       rwdts.XactFlag.ADVISE,
                                                       response_info)
                 else:
+                    self._log.debug("VDU create monitor at {}".format(response_xpath))
                     asyncio.ensure_future(monitor_vdu_state(response_xpath, pathentry),
                                           loop = self._loop)
 
-
         @asyncio.coroutine
         def on_vdu_request_prepare(xact_info, action, ks_path, request_msg):
             self._log.debug("Received vdu on_prepare callback (xact_info: %s, action: %s): %s",
                             xact_info, action, request_msg)
             response_xpath = ks_path.to_xpath(RwResourceMgrYang.get_schema()) + "/resource-info"
+            response_xpath = self._add_config_flag(response_xpath)
             schema = RwResourceMgrYang.VDUEventData().schema()
             pathentry = schema.keyspec_to_entry(ks_path)
 
@@ -269,7 +292,12 @@
                 yield from self._parent.release_virtual_compute(pathentry.key00.event_id)
                 self.delete_record_dts(self._vdu_reg, None, ks_path.to_xpath(RwResourceMgrYang.get_schema()))
             elif action == rwdts.QueryAction.READ:
-                response_info = yield from self._parent.read_virtual_compute_info(pathentry.key00.event_id)
+                # TODO: Check why we are getting null event id request
+                if pathentry.key00.event_id:
+                    response_info = yield from self._parent.read_virtual_compute_info(pathentry.key00.event_id)
+                else:
+                    xact_info.respond_xpath(rwdts.XactRspCode.NA)
+                    return
             else:
                 raise ValueError("Only create/delete actions available. Received action: %s" %(action))
 
@@ -293,24 +321,37 @@
 
         link_handlers = rift.tasklets.Group.Handler(on_event=onlink_event,)
         with self._dts.group_create(handler=link_handlers) as link_group:
-            self._log.debug("Registering for Link Resource Request using xpath: %s",
-                            ResourceMgrEvent.VLINK_REQUEST_XPATH)
+            xpath = self._project.add_project(ResourceMgrEvent.VLINK_REQUEST_XPATH)
+            self._log.debug("Registering for Link Resource Request using xpath: {}".
+                            format(xpath))
 
-            self._link_reg = link_group.register(xpath=ResourceMgrEvent.VLINK_REQUEST_XPATH,
-                                            handler=rift.tasklets.DTS.RegistrationHandler(on_ready=on_request_ready,
-                                                                                          on_commit=on_link_request_commit,
-                                                                                          on_prepare=on_link_request_prepare),
-                                            flags=rwdts.Flag.PUBLISHER | rwdts.Flag.DATASTORE,)
+            self._link_reg = link_group.register(xpath=xpath,
+                handler=rift.tasklets.DTS.RegistrationHandler(on_ready=on_request_ready,
+                                                              on_commit=on_link_request_commit,
+                                                              on_prepare=on_link_request_prepare),
+                                                 flags=rwdts.Flag.PUBLISHER | rwdts.Flag.DATASTORE,)
 
         vdu_handlers = rift.tasklets.Group.Handler(on_event=onvdu_event, )
         with self._dts.group_create(handler=vdu_handlers) as vdu_group:
 
-            self._log.debug("Registering for VDU Resource Request using xpath: %s",
-                            ResourceMgrEvent.VDU_REQUEST_XPATH)
+            xpath = self._project.add_project(ResourceMgrEvent.VDU_REQUEST_XPATH)
+            self._log.debug("Registering for VDU Resource Request using xpath: {}".
+                            format(xpath))
 
-            self._vdu_reg = vdu_group.register(xpath=ResourceMgrEvent.VDU_REQUEST_XPATH,
-                                           handler=rift.tasklets.DTS.RegistrationHandler(on_ready=on_request_ready,
-                                                                                         on_commit=on_vdu_request_commit,
-                                                                                         on_prepare=on_vdu_request_prepare),
-                                           flags=rwdts.Flag.PUBLISHER | rwdts.Flag.DATASTORE,)
+            self._vdu_reg = vdu_group.register(xpath=xpath,
+                handler=rift.tasklets.DTS.RegistrationHandler(on_ready=on_request_ready,
+                                                              on_commit=on_vdu_request_commit,
+                                                              on_prepare=on_vdu_request_prepare),
+                                               flags=rwdts.Flag.PUBLISHER | rwdts.Flag.DATASTORE,)
 
+
+    def deregister(self):
+        self._log.debug("De-register for project {}".format(self._project.name))
+
+        if self._vdu_reg:
+            self._vdu_reg.deregister()
+            self._vdu_reg = None
+
+        if self._link_reg:
+            self._link_reg.deregister()
+            self._link_reg = None
diff --git a/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgrtasklet.py b/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgrtasklet.py
index cdcadc7..d235915 100755
--- a/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgrtasklet.py
+++ b/rwlaunchpad/plugins/rwresmgr/rift/tasklets/rwresmgrtasklet/rwresmgrtasklet.py
@@ -34,6 +34,10 @@
 )
 
 import rift.tasklets
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+)
 
 from . import rwresmgr_core as Core
 from . import rwresmgr_config as Config
@@ -41,11 +45,13 @@
 
 
 class ResourceManager(object):
-    def __init__(self, log, log_hdl, loop, dts):
+    def __init__(self, log, log_hdl, loop, dts, project):
         self._log            = log
         self._log_hdl        = log_hdl
         self._loop           = loop
         self._dts            = dts
+        self._project        = project
+
         self.config_handler  = Config.ResourceMgrConfig(self._dts, self._log, self._log_hdl, self._loop, self)
         self.event_handler   = Event.ResourceMgrEvent(self._dts, self._log, self._loop, self)
         self.core            = Core.ResourceMgrCore(self._dts, self._log, self._log_hdl, self._loop, self)
@@ -55,6 +61,10 @@
         yield from self.config_handler.register()
         yield from self.event_handler.register()
 
+    def deregister(self):
+        self.event_handler.deregister()
+        self.config_handler.deregister()
+
     def add_cloud_account_config(self, account):
         self._log.debug("Received Cloud-Account add config event for account: %s", account.name)
         self.core.add_cloud_account(account)
@@ -160,16 +170,45 @@
         return info
 
 
+class ResMgrProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(ResMgrProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self._resource_manager = None
+
+    @asyncio.coroutine
+    def register (self):
+        self._log.debug("Initializing the Resource Manager tasklet for project {}".
+                        format(self.name))
+        self._resource_manager = ResourceManager(self._log,
+                                                 self._log_hdl,
+                                                 self._loop,
+                                                 self._dts,
+                                                 self,)
+        yield from self._resource_manager.register()
+
+    def deregister(self):
+        self._log.debug("De-registering project {}".format(self.name))
+        self._resource_manager.deregister()
+
+
 class ResMgrTasklet(rift.tasklets.Tasklet):
     def __init__(self, *args, **kwargs):
         super(ResMgrTasklet, self).__init__(*args, **kwargs)
         self.rwlog.set_category("rw-resource-mgr-log")
         self._dts = None
-        self._resource_manager = None
+        self._project_handler = None
+        self.projects = {}
+
+    @property
+    def dts(self):
+        return self._dts
 
     def start(self):
         super(ResMgrTasklet, self).start()
-        self.log.info("Starting ResMgrTasklet")
+        self.log.debug("Starting ResMgrTasklet")
 
         self.log.debug("Registering with dts")
 
@@ -192,12 +231,9 @@
 
     @asyncio.coroutine
     def init(self):
-        self._log.info("Initializing the Resource Manager tasklet")
-        self._resource_manager = ResourceManager(self.log,
-                                                 self.log_hdl,
-                                                 self.loop,
-                                                 self._dts)
-        yield from self._resource_manager.register()
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, ResMgrProject)
+        self.project_handler.register()
 
     @asyncio.coroutine
     def run(self):
diff --git a/rwlaunchpad/plugins/rwresmgr/test/rmmgr_test.py b/rwlaunchpad/plugins/rwresmgr/test/rmmgr_test.py
index 17c5bf0..c0b4788 100755
--- a/rwlaunchpad/plugins/rwresmgr/test/rmmgr_test.py
+++ b/rwlaunchpad/plugins/rwresmgr/test/rmmgr_test.py
@@ -441,7 +441,7 @@
 
     @asyncio.coroutine
     def configure_compute_resource_pools(self, dts, resource_type, cloud_type):
-        pool_xpath = "C,/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools"
+        pool_xpath = "C,/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools"
         msg = self.get_compute_pool_msg("virtual-compute", resource_type, cloud_type)
         self.log.info("Configuring compute-resource-pool: %s",msg)
         yield from dts.query_create(pool_xpath,
@@ -451,7 +451,7 @@
 
     @asyncio.coroutine
     def configure_network_resource_pools(self, dts, resource_type, cloud_type):
-        pool_xpath = "C,/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools"
+        pool_xpath = "C,/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools"
         msg = self.get_network_pool_msg("virtual-network", resource_type, cloud_type)
         self.log.info("Configuring network-resource-pool: %s",msg)
         yield from dts.query_create(pool_xpath,
@@ -460,7 +460,7 @@
 
     @asyncio.coroutine
     def verify_resource_pools_config(self, dts):
-        pool_records_xpath = "D,/rw-resource-mgr:resource-pool-records"
+        pool_records_xpath = "D,/rw-project:project/rw-resource-mgr:resource-pool-records"
         self.log.debug("Verifying test_create_resource_pools results")
         res_iter = yield from dts.query_read(pool_records_xpath,)
         for result in res_iter:
@@ -491,7 +491,7 @@
 
     @asyncio.coroutine
     def reserve_network_resources(self, name, dts, cloud_type):
-        network_xpath = "D,/rw-resource-mgr:resource-mgmt/vlink-event/vlink-event-data[event-id='{}']"
+        network_xpath = "D,/rw-project:project/rw-resource-mgr:resource-mgmt/vlink-event/vlink-event-data[event-id='{}']"
         msg,xpath = self.get_network_reserve_msg(name, cloud_type, network_xpath)
         self.log.debug("Sending create event to network-event xpath %s with msg: %s" % (xpath, msg))
         yield from dts.query_create(xpath, 0, msg)
@@ -500,7 +500,7 @@
 
     @asyncio.coroutine
     def reserve_compute_resources(self, name, dts, cloud_type, vlinks = []):
-        compute_xpath = "D,/rw-resource-mgr:resource-mgmt/vdu-event/vdu-event-data[event-id='{}']"
+        compute_xpath = "D,/rw-project:project/rw-resource-mgr:resource-mgmt/vdu-event/vdu-event-data[event-id='{}']"
         msg,xpath = self.get_compute_reserve_msg(name, cloud_type, compute_xpath, vlinks)
         self.log.debug("Sending create event to compute-event xpath %s with msg: %s" % (xpath, msg))
         yield from dts.query_create(xpath, 0, msg)
diff --git a/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/publisher/staging_status.py b/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/publisher/staging_status.py
index 82e2da5..36c36f6 100644
--- a/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/publisher/staging_status.py
+++ b/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/publisher/staging_status.py
@@ -28,13 +28,13 @@
 
 class StagingStorePublisher(mano_dts.DtsHandler, StagingStoreProtocol):
 
-    def __init__(self, log, dts, loop):
-        super().__init__(log, dts, loop)
+    def __init__(self, project):
+        super().__init__(project.log, project.dts, project.loop, project)
         self.delegate = None
 
     def xpath(self, area_id=None):
-        return ("D,/rw-staging-mgmt:staging-areas/rw-staging-mgmt:staging-area" +
-            ("[area-id='{}']".format(area_id) if area_id else ""))
+        return self.project.add_project("D,/rw-staging-mgmt:staging-areas/rw-staging-mgmt:staging-area" +
+                                        ("[area-id='{}']".format(area_id) if area_id else ""))
 
     @asyncio.coroutine
     def register(self):
@@ -59,6 +59,12 @@
 
         assert self.reg is not None
 
+    def deregister(self):
+        self._log.debug("Project {}: de-register staging store handler".
+                        format(self._project.name))
+        if self.reg:
+            self.reg.deregister()
+
     def on_staging_area_create(self, store):
         self.reg.update_element(self.xpath(store.area_id), store)
 
diff --git a/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/rwstagingmgr.py b/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/rwstagingmgr.py
index 04a7cae..4cb6553 100644
--- a/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/rwstagingmgr.py
+++ b/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/rwstagingmgr.py
@@ -36,6 +36,10 @@
         RwDts as rwdts,
         RwStagingMgmtYang)
 import rift.tasklets
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+)
 
 from . import rpc
 from . import store
@@ -43,14 +47,36 @@
 from .publisher import StagingStorePublisher
 
 
+class StagingManagerProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(StagingManagerProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self.publisher = StagingStorePublisher(self)
+        # For recovery
+        self.publisher.delegate = tasklet.store
+
+    @asyncio.coroutine
+    def register (self):
+        yield from self.publisher.register()
+
+    def deregister(self):
+        self.publisher.deregister()
+
+
 class StagingManagerTasklet(rift.tasklets.Tasklet):
     """Tasklet to handle all staging related operations
     """
     def __init__(self, *args, **kwargs):
         try:
             super().__init__(*args, **kwargs)
+            self._project_handler = None
+            self.projects = {}
+
         except Exception as e:
-            self.log.exception(e)
+            self.log.exception("Staging Manager tasklet init: {}".
+                               format(e))
 
     def start(self):
         super().start()
@@ -72,14 +98,7 @@
 
     @asyncio.coroutine
     def init(self):
-        self.store = store.StagingFileStore(log=self.log)
-        self.publisher = StagingStorePublisher(self.log, self.dts, self.loop)
-        # Fore recovery
-        self.publisher.delegate = self.store
-        # For create and delete events
-        self.store.delegate = self.publisher
-        yield from self.publisher.register()
-
+        self.store = store.StagingFileStore(self)
 
         io_loop = rift.tasklets.tornado.TaskletAsyncIOLoop(asyncio_loop=self.loop)
         self.app = StagingApplication(self.store)
@@ -107,9 +126,12 @@
                 self.dts,
                 self.loop,
                 self.store)
-
         yield from self.create_stg_rpc.register()
 
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, StagingManagerProject)
+        self.project_handler.register()
+
     @asyncio.coroutine
     def run(self):
         self.server.listen(self.app.PORT)
diff --git a/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/store/file_store.py b/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/store/file_store.py
index aec4180..8acefe1 100644
--- a/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/store/file_store.py
+++ b/rwlaunchpad/plugins/rwstagingmgr/rift/tasklets/rwstagingmgr/store/file_store.py
@@ -53,7 +53,7 @@
     META_YAML = "meta.yaml"
     DEFAULT_EXPIRY = 60 * 60
 
-    def __init__(self, log=None, root_dir=None):
+    def __init__(self, tasklet, root_dir=None):
         default_path = os.path.join(
             os.getenv('RIFT_ARTIFACTS'),
             "launchpad/staging")
@@ -63,11 +63,11 @@
         if not os.path.isdir(self.root_dir):
             os.makedirs(self.root_dir)
 
-        self.log = log or logging.getLogger()
+        self.log = tasklet.log
         self.tmp_dir = tempfile.mkdtemp(dir=self.root_dir)
 
         self._cache = {}
-        self.delegate = None
+        self.tasklet = tasklet
 
     def on_recovery(self, staging_areas):
         for area in staging_areas:
@@ -82,6 +82,17 @@
         return self._cache[area_id]
 
 
+    def get_delegate(self, msg):
+        try:
+            proj = self.tasklet.projects[msg.project_name]
+        except Exception as e:
+            err = "Project or project name not found {}: {}". \
+                  format(msg.as_dict(), e)
+            self.log.error (err)
+            raise Exception (err)
+
+        return proj.publisher
+
     def create_staging_area(self, staging_area_config):
         """Create the staging area
         Args:
@@ -93,6 +104,8 @@
         Raises:
             StagingAreaExists: if the staging area already exists
         """
+        delegate = self.get_delegate(staging_area_config)
+
         area_id = str(uuid.uuid4())
 
         container_path = os.path.join(self.root_dir, str(area_id))
@@ -118,10 +131,10 @@
         self._cache[area_id] = staging_area
 
         try:
-            if self.delegate:
-                self.delegate.on_staging_area_create(staging_area.model)
+            if delegate:
+                delegate.on_staging_area_create(staging_area.model)
         except Exception as e:
-            self.log.exception(str(e))
+            self.log.exception(e)
 
         return staging_area
 
@@ -131,6 +144,8 @@
             staging_area (str or model.StagingArea): Staging ID or the
                 StagingArea object
         """
+        delegate = self.get_delegate(staging_area_config)
+
         if type(staging_area) is str:
             staging_area = self.get_staging_area(staging_area)
 
@@ -140,7 +155,7 @@
         staging_area.model.status = "EXPIRED"
 
         try:
-            if self.delegate:
-                self.delegate.on_staging_area_delete(staging_area.model)
+            if delegate:
+                delegate.on_staging_area_delete(staging_area.model)
         except Exception as e:
-            self.log.exception(str(e))
+            self.log.exception(e)
diff --git a/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py b/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py
index 5ff2983..abf73ae 100755
--- a/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py
+++ b/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py
@@ -51,6 +51,10 @@
 import rift.package.cloud_init
 import rift.package.script
 import rift.mano.dts as mano_dts
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+    )
 
 
 class VMResourceError(Exception):
@@ -162,7 +166,8 @@
 
 class VcsComponent(object):
     """ VCS Component within the VNF descriptor """
-    def __init__(self, dts, log, loop, cluster_name, vcs_handler, component, mangled_name):
+    def __init__(self, dts, log, loop, cluster_name,
+                 vcs_handler, component, mangled_name):
         self._dts = dts
         self._log = log
         self._loop = loop
@@ -184,7 +189,7 @@
     @property
     def path(self):
         """ The path for this object """
-        return("D,/rw-manifest:manifest" +
+        return ("D,/rw-manifest:manifest" +
                "/rw-manifest:operational-inventory" +
                "/rw-manifest:component" +
                "[rw-manifest:component-name = '{}']").format(self.name)
@@ -269,6 +274,7 @@
                  dts,
                  log,
                  loop,
+                 project,
                  vdud,
                  vnfr,
                  mgmt_intf,
@@ -280,6 +286,7 @@
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._vdud = vdud
         self._vnfr = vnfr
         self._mgmt_intf = mgmt_intf
@@ -298,7 +305,8 @@
         self._rm_regh = None
         self._vm_resp = None
         self._vdud_cloud_init = None
-        self._vdur_console_handler = VnfrConsoleOperdataDtsHandler(dts, log, loop, self._vnfr._vnfm, self._vnfr.vnfr_id, self._vdur_id,self.vdu_id)
+        self._vdur_console_handler = VnfrConsoleOperdataDtsHandler(
+            dts, log, loop, self._vnfr._vnfm, self._vnfr.vnfr_id, self._vdur_id,self.vdu_id)
 
     @asyncio.coroutine
     def vdu_opdata_register(self):
@@ -479,14 +487,15 @@
             placement_groups.append(group.as_dict())
         vdur_dict['placement_groups_info'] = placement_groups
 
-        return RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur.from_dict(vdur_dict)
+        return RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur.from_dict(vdur_dict)
 
     @property
     def resmgr_path(self):
         """ path for resource-mgr"""
-        return ("D,/rw-resource-mgr:resource-mgmt" +
-                "/vdu-event" +
-                "/vdu-event-data[event-id='{}']".format(self._request_id))
+        xpath = self._project.add_project("D,/rw-resource-mgr:resource-mgmt" +
+                                          "/vdu-event" +
+                                          "/vdu-event-data[event-id='{}']".format(self._request_id))
+        return xpath
 
     @property
     def vm_flavor_msg(self):
@@ -541,15 +550,19 @@
 
         if availability_zones:
             if len(availability_zones) > 1:
-                self._log.error("Can not launch VDU: %s in multiple availability zones. Requested Zones: %s", self.name, availability_zones)
-                raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple availability zones. Requsted Zones".format(self.name, availability_zones))
+                self._log.error("Can not launch VDU: %s in multiple availability zones. " +
+                                "Requested Zones: %s", self.name, availability_zones)
+                raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple availability" +
+                                              " zones. Requsted Zones".format(self.name, availability_zones))
             else:
                 vm_create_msg_dict['availability_zone'] = availability_zones[0]
 
         if server_groups:
             if len(server_groups) > 1:
-                self._log.error("Can not launch VDU: %s in multiple Server Group. Requested Groups: %s", self.name, server_groups)
-                raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple Server Groups. Requsted Groups".format(self.name, server_groups))
+                self._log.error("Can not launch VDU: %s in multiple Server Group. " +
+                                "Requested Groups: %s", self.name, server_groups)
+                raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple " +
+                                              "Server Groups. Requsted Groups".format(self.name, server_groups))
             else:
                 vm_create_msg_dict['server_group'] = server_groups[0]
 
@@ -702,7 +715,7 @@
             self._rm_regh = None
 
         if self._vdur_console_handler is not None:
-            self._log.error("Deregistering vnfr vdur registration handle")
+            self._log.debug("Deregistering vnfr vdur registration handle")
             self._vdur_console_handler._regh.deregister()
             self._vdur_console_handler._regh = None
 
@@ -995,10 +1008,12 @@
 
 class InternalVirtualLinkRecord(object):
     """ Internal Virtual Link record """
-    def __init__(self, dts, log, loop, ivld_msg, vnfr_name, cloud_account_name, ip_profile=None):
+    def __init__(self, dts, log, loop, project,
+                 ivld_msg, vnfr_name, cloud_account_name, ip_profile=None):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._ivld_msg = ivld_msg
         self._vnfr_name = vnfr_name
         self._cloud_account_name = cloud_account_name
@@ -1028,7 +1043,8 @@
 
     def vlr_path(self):
         """ VLR path for this VLR instance"""
-        return "D,/vlr:vlr-catalog/vlr:vlr[vlr:id = '{}']".format(self.vlr_id)
+        return self._project.add_project("D,/vlr:vlr-catalog/vlr:vlr[vlr:id = '{}']".
+                                         format(self.vlr_id))
 
     def create_vlr(self):
         """ Create the VLR record which will be instantiated """
@@ -1053,7 +1069,7 @@
 
         vlr_dict.update(vld_copy_dict)
 
-        vlr = RwVlrYang.YangData_Vlr_VlrCatalog_Vlr.from_dict(vlr_dict)
+        vlr = RwVlrYang.YangData_RwProject_Project_VlrCatalog_Vlr.from_dict(vlr_dict)
         return vlr
 
     @asyncio.coroutine
@@ -1150,6 +1166,7 @@
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = vnfm._project
         self._cluster_name = cluster_name
         self._vnfr_msg = vnfr_msg
         self._vnfr_id = vnfr_msg.id
@@ -1202,7 +1219,8 @@
     @staticmethod
     def vnfd_xpath(vnfd_id):
         """ VNFD xpath associated with this VNFR """
-        return "C,/vnfd:vnfd-catalog/vnfd:vnfd[vnfd:id = '{}']".format(vnfd_id)
+        return ("C,/vnfd:vnfd-catalog/vnfd:vnfd[vnfd:id = '{}']".
+                format(vnfd_id))
 
     @property
     def vnfd_ref_count(self):
@@ -1283,7 +1301,7 @@
     def get_nsr_config(self):
         ### Need access to NS instance configuration for runtime resolution.
         ### This shall be replaced when deployment flavors are implemented
-        xpath = "C,/nsr:ns-instance-config"
+        xpath = self._project.add_project("C,/nsr:ns-instance-config")
         results = yield from self._dts.query_read(xpath, rwdts.XactFlag.MERGE)
 
         for result in results:
@@ -1333,7 +1351,7 @@
         vnfd_fields = ["short_name", "vendor", "description", "version"]
         vnfd_copy_dict = {k: v for k, v in self.vnfd.as_dict().items() if k in vnfd_fields}
 
-        mgmt_intf = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MgmtInterface()
+        mgmt_intf = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MgmtInterface()
         ip_address, port = self.mgmt_intf_info()
 
         if ip_address is not None:
@@ -1353,8 +1371,8 @@
 
         vnfr_dict.update(vnfd_copy_dict)
 
-        vnfr_msg = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict(vnfr_dict)
-        vnfr_msg.vnfd = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict())
+        vnfr_msg = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.from_dict(vnfr_dict)
+        vnfr_msg.vnfd = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict())
 
         vnfr_msg.create_time = self._create_time
         vnfr_msg.uptime = int(time.time()) - self._create_time
@@ -1375,13 +1393,13 @@
             vnfr_msg.dashboard_url = self.dashboard_url
 
         for cpr in self._cprs:
-            new_cp = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr.as_dict())
+            new_cp = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr.as_dict())
             vnfr_msg.connection_point.append(new_cp)
 
         if self._vnf_mon is not None:
             for monp in self._vnf_mon.msg:
                 vnfr_msg.monitoring_param.append(
-                    VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MonitoringParam.from_dict(monp.as_dict()))
+                    VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam.from_dict(monp.as_dict()))
 
         if self._vnfr.vnf_configuration is not None:
             vnfr_msg.vnf_configuration.from_dict(self._vnfr.vnf_configuration.as_dict())
@@ -1390,7 +1408,7 @@
                 vnfr_msg.vnf_configuration.config_access.mgmt_ip_address = ip_address
 
         for group in self._vnfr_msg.placement_groups_info:
-            group_info = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_PlacementGroupsInfo()
+            group_info = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_PlacementGroupsInfo()
             group_info.from_dict(group.as_dict())
             vnfr_msg.placement_groups_info.append(group_info)
 
@@ -1420,7 +1438,7 @@
     @property
     def xpath(self):
         """ path for this  VNFR """
-        return("D,/vnfr:vnfr-catalog"
+        return self._project.add_project("D,/vnfr:vnfr-catalog"
                "/vnfr:vnfr[vnfr:id='{}']".format(self.vnfr_id))
 
     @asyncio.coroutine
@@ -1495,7 +1513,7 @@
         for group_info in nsr_config.vnfd_placement_group_maps:
             if group_info.placement_group_ref == input_group.name and \
                group_info.vnfd_id_ref == self.vnfd_id:
-                group = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo()
+                group = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo()
                 group_dict = {k:v for k,v in
                               group_info.as_dict().items()
                               if (k != 'placement_group_ref' and k !='vnfd_id_ref')}
@@ -1510,7 +1528,7 @@
         placement_groups = []
         ### Step-1: Get VNF level placement groups
         for group in self._vnfr_msg.placement_groups_info:
-            #group_info = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo()
+            #group_info = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo()
             #group_info.from_dict(group.as_dict())
             placement_groups.append(group)
 
@@ -1524,10 +1542,11 @@
                     group_info = self.resolve_placement_group_cloud_construct(group,
                                                                               nsr_config)
                     if group_info is None:
-                        self._log.info("Could not resolve cloud-construct for placement group: %s", group.name)
-                        ### raise VNFMPlacementGroupError("Could not resolve cloud-construct for placement group: {}".format(group.name))
+                        self._log.info("Could not resolve cloud-construct for " +
+                                       "placement group: %s", group.name)
                     else:
-                        self._log.info("Successfully resolved cloud construct for placement group: %s for VDU: %s in VNF: %s (Member Index: %s)",
+                        self._log.info("Successfully resolved cloud construct for " +
+                                       "placement group: %s for VDU: %s in VNF: %s (Member Index: %s)",
                                        str(group_info),
                                        vdu.name,
                                        self.vnf_name,
@@ -1579,6 +1598,7 @@
                 dts=self._dts,
                 log=self._log,
                 loop=self._loop,
+                project = self._project,
                 vdud=vdu,
                 vnfr=vnfr,
                 mgmt_intf=self.has_mgmt_interface(vdu),
@@ -1725,8 +1745,7 @@
 
     def vlr_xpath(self, vlr_id):
         """ vlr xpath """
-        return(
-            "D,/vlr:vlr-catalog/"
+        return self._project.add_project("D,/vlr:vlr-catalog/"
             "vlr:vlr[vlr:id = '{}']".format(vlr_id))
 
     def ext_vlr_by_id(self, vlr_id):
@@ -1816,6 +1835,7 @@
     @asyncio.coroutine
     def instantiate(self, xact, restart_mode=False):
         """ instantiate this VNF """
+        self._log.info("Instantiate VNF {}: {}".format(self._vnfr_id, self._state))
         self.set_state(VirtualNetworkFunctionRecordState.VL_INIT_PHASE)
         self._rw_vnfd = yield from self._vnfm.fetch_vnfd(self._vnfd_id)
 
@@ -1831,7 +1851,7 @@
                 cp_copy_dict = {k: v for k, v in cp.as_dict().items() if k in cp_fields}
                 cpr_dict = {}
                 cpr_dict.update(cp_copy_dict)
-                return VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr_dict)
+                return VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr_dict)
 
             self._log.debug("Fetching VLRs for VNFR id = %s, cps = %s",
                             self._vnfr_id, self._vnfr.connection_point)
@@ -1843,7 +1863,7 @@
 
                 vlr_path = self.vlr_xpath(cp.vlr_ref)
                 self._log.debug("Fetching VLR with path = %s", vlr_path)
-                res_iter = yield from self._dts.query_read(self.vlr_xpath(cp.vlr_ref),
+                res_iter = yield from self._dts.query_read(vlr_path,
                                                            rwdts.XactFlag.MERGE)
                 for i in res_iter:
                     r = yield from i
@@ -1866,16 +1886,16 @@
         yield from self.publish_inventory(xact)
 
         # Publish inventory
-        self._log.debug("VNFR-ID %s: Creating VLs", self._vnfr_id)
+        self._log.debug("Create VLs {}: {}".format(self._vnfr_id, self._state))
         yield from self.create_vls()
 
         # publish the VNFR
-        self._log.debug("VNFR-ID %s: Publish VNFR", self._vnfr_id)
+        self._log.debug("Publish VNFR {}: {}".format(self._vnfr_id, self._state))
         yield from self.publish(xact)
 
 
         # instantiate VLs
-        self._log.debug("VNFR-ID %s: Instantiate VLs", self._vnfr_id)
+        self._log.debug("Instantiate VLs {}: {}".format(self._vnfr_id, self._state))
         try:
             yield from self.instantiate_vls(xact, restart_mode)
         except Exception as e:
@@ -1886,7 +1906,7 @@
         self.set_state(VirtualNetworkFunctionRecordState.VM_INIT_PHASE)
 
         # instantiate VDUs
-        self._log.debug("VNFR-ID %s: Create VDUs", self._vnfr_id)
+        self._log.debug("Create VDUs {}: {}".format(self._vnfr_id, self._state))
         yield from self.create_vdus(self, restart_mode)
 
         try:
@@ -1897,12 +1917,13 @@
             yield from self.publish(xact)
 
         # publish the VNFR
-        self._log.debug("VNFR-ID %s: Publish VNFR", self._vnfr_id)
+        self._log.debug("VNFR {}: Publish VNFR with state {}".
+                        format(self._vnfr_id, self._state))
         yield from self.publish(xact)
 
         # instantiate VDUs
         # ToDo: Check if this should be prevented during restart
-        self._log.debug("VNFR-ID %s: Instantiate VDUs", self._vnfr_id)
+        self._log.debug("Instantiate VDUs {}: {}".format(self._vnfr_id, self._state))
         _ = self._loop.create_task(self.instantiate_vdus(xact, self))
 
         # publish the VNFR
@@ -1982,6 +2003,14 @@
         """ DTS registration handle """
         return self._regh
 
+    def deregister(self):
+        '''De-register from DTS'''
+        self._log.debug("De-register VNFD DTS handler for project {}".
+                        format(self._project))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Register for VNFD configuration"""
@@ -2014,14 +2043,14 @@
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
-        self._log.debug(
-            "Registering for VNFD config using xpath: %s",
-            VnfdDtsHandler.XPATH,
-            )
+        xpath = self._vnfm._project.add_project(VnfdDtsHandler.XPATH)
+        self._log.debug("Registering for VNFD config using xpath: {}".
+                        format(xpath))
+
         acg_hdl = rift.tasklets.AppConfGroup.Handler(on_apply=on_apply)
         with self._dts.appconf_group_create(handler=acg_hdl) as acg:
             self._regh = acg.register(
-                xpath=VnfdDtsHandler.XPATH,
+                xpath=xpath,
                 flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
                 on_prepare=on_prepare)
 
@@ -2044,6 +2073,14 @@
         """ DTS registration handle """
         return self._regh
 
+    def deregister(self):
+        '''De-register from DTS'''
+        self._log.debug("De-register VCS DTS handler for project {}".
+                        format(self._project))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Registers VCS component dts publisher registration"""
@@ -2069,11 +2106,16 @@
                         VcsComponentDtsHandler.XPATH, xact, path, msg)
 
 class VnfrConsoleOperdataDtsHandler(object):
-    """ registers 'D,/vnfr:vnfr-console/vnfr:vnfr[id]/vdur[id]' and handles CRUD from DTS"""
+    """
+    Registers 'D,/rw-project:project/vnfr:vnfr-console/vnfr:vnfr[id]/vdur[id]'
+    and handles CRUD from DTS
+    """
+
     @property
     def vnfr_vdu_console_xpath(self):
         """ path for resource-mgr"""
-        return ("D,/rw-vnfr:vnfr-console/rw-vnfr:vnfr[rw-vnfr:id='{}']/rw-vnfr:vdur[vnfr:id='{}']".format(self._vnfr_id,self._vdur_id))
+        return self._project.add_project("D,/rw-vnfr:vnfr-console/rw-vnfr:vnfr[rw-vnfr:id='{}']" +
+                                         "/rw-vnfr:vdur[vnfr:id='{}']".format(self._vnfr_id,self._vdur_id))
 
     def __init__(self, dts, log, loop, vnfm, vnfr_id, vdur_id, vdu_id):
         self._dts = dts
@@ -2086,6 +2128,16 @@
         self._vdur_id = vdur_id
         self._vdu_id = vdu_id
 
+        self._project = vnfm._project
+
+    def deregister(self):
+        '''De-register from DTS'''
+        self._log.debug("De-register VNFR console DTS handler for project {}".
+                        format(self._project))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Register for VNFR VDU Operational Data read from dts """
@@ -2100,7 +2152,7 @@
                 )
 
             if action == rwdts.QueryAction.READ:
-                schema = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur.schema()
+                schema = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
                 self._log.debug("VDU Opdata path is {}".format(path_entry))
                 try:
@@ -2117,7 +2169,7 @@
                         return
                     with self._dts.transaction() as new_xact:
                         resp = yield from vdur.read_resource(new_xact)
-                        vdur_console = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur()
+                        vdur_console = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur()
                         vdur_console.id = self._vdur_id
                         if resp.console_url:
                             vdur_console.console_url = resp.console_url
@@ -2126,7 +2178,7 @@
                         self._log.debug("Recevied console URL for vdu {} is {}".format(self._vdu_id,vdur_console))
                 except Exception:
                     self._log.exception("Caught exception while reading VDU %s", self._vdu_id)
-                    vdur_console = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur()
+                    vdur_console = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur()
                     vdur_console.id = self._vdur_id
                     vdur_console.console_url = 'none'
 
@@ -2151,7 +2203,7 @@
 
 
 class VnfrDtsHandler(object):
-    """ registers 'D,/vnfr:vnfr-catalog/vnfr:vnfr' and handles CRUD from DTS"""
+    """ registers 'D,/rw-project:project/vnfr:vnfr-catalog/vnfr:vnfr' and handles CRUD from DTS"""
     XPATH = "D,/vnfr:vnfr-catalog/vnfr:vnfr"
 
     def __init__(self, dts, log, loop, vnfm):
@@ -2161,6 +2213,7 @@
         self._vnfm = vnfm
 
         self._regh = None
+        self._project = vnfm._project
 
     @property
     def regh(self):
@@ -2172,6 +2225,14 @@
         """ Return VNF manager instance """
         return self._vnfm
 
+    def deregister(self):
+        '''De-register from DTS'''
+        self._log.debug("De-register VNFR DTS handler for project {}".
+                        format(self._project))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Register for vnfr create/update/delete/read requests from dts """
@@ -2233,7 +2294,7 @@
                     vnfr.set_state(VirtualNetworkFunctionRecordState.FAILED)
                     yield from vnfr.publish(None)
             elif action == rwdts.QueryAction.DELETE:
-                schema = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.schema()
+                schema = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
                 vnfr = self._vnfm.get_vnfr(path_entry.key00.id)
 
@@ -2252,7 +2313,7 @@
                     self._log.error("Caught exception while deleting vnfr %s", path_entry.key00.id)
 
             elif action == rwdts.QueryAction.UPDATE:
-                schema = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.schema()
+                schema = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
                 vnfr = None
                 try:
@@ -2280,14 +2341,15 @@
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
-        self._log.debug("Registering for VNFR using xpath: %s",
-                        VnfrDtsHandler.XPATH,)
+        xpath = self._project.add_project(VnfrDtsHandler.XPATH)
+        self._log.debug("Registering for VNFR using xpath: {}".
+                        format(xpath))
 
         hdl = rift.tasklets.DTS.RegistrationHandler(on_commit=on_commit,
                                                     on_prepare=on_prepare,)
         handlers = rift.tasklets.Group.Handler(on_event=on_event,)
         with self._dts.group_create(handler=handlers) as group:
-            self._regh = group.register(xpath=VnfrDtsHandler.XPATH,
+            self._regh = group.register(xpath=xpath,
                                         handler=hdl,
                                         flags=(rwdts.Flag.PUBLISHER |
                                                rwdts.Flag.NO_PREP_READ |
@@ -2295,10 +2357,11 @@
                                                rwdts.Flag.DATASTORE),)
 
     @asyncio.coroutine
-    def create(self, xact, path, msg):
+    def create(self, xact, xpath, msg):
         """
         Create a VNFR record in DTS with path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Creating VNFR xact = %s, %s:%s",
                         xact, path, msg)
 
@@ -2307,10 +2370,11 @@
                         xact, path, msg)
 
     @asyncio.coroutine
-    def update(self, xact, path, msg):
+    def update(self, xact, xpath, msg):
         """
         Update a VNFR record in DTS with path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Updating VNFR xact = %s, %s:%s",
                         xact, path, msg)
         self.regh.update_element(path, msg)
@@ -2318,10 +2382,11 @@
                         xact, path, msg)
 
     @asyncio.coroutine
-    def delete(self, xact, path):
+    def delete(self, xact, xpath):
         """
         Delete a VNFR record in DTS with path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Deleting VNFR xact = %s, %s", xact, path)
         self.regh.delete_element(path)
         self._log.debug("Deleted VNFR xact = %s, %s", xact, path)
@@ -2349,6 +2414,14 @@
         """ Return the NS manager instance """
         return self._vnfm
 
+    def deregister(self):
+        '''De-register from DTS'''
+        self._log.debug("De-register VNFD Ref DTS handler for project {}".
+                        format(self._project))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Register for VNFD ref count read from dts """
@@ -2363,7 +2436,7 @@
                 )
 
             if action == rwdts.QueryAction.READ:
-                schema = RwVnfrYang.YangData_Vnfr_VnfrCatalog_VnfdRefCount.schema()
+                schema = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_VnfdRefCount.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
                 vnfd_list = yield from self._vnfm.get_vnfd_refcount(path_entry.key00.vnfd_id_ref)
                 for xpath, msg in vnfd_list:
@@ -2378,7 +2451,8 @@
 
         hdl = rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare,)
         with self._dts.group_create() as group:
-            self._regh = group.register(xpath=VnfdRefCountDtsHandler.XPATH,
+            self._regh = group.register(xpath=self._vnfm._project.add_project(
+                VnfdRefCountDtsHandler.XPATH),
                                         handler=hdl,
                                         flags=rwdts.Flag.PUBLISHER,
                                         )
@@ -2506,16 +2580,18 @@
 
 class VnfManager(object):
     """ The virtual network function manager class """
-    def __init__(self, dts, log, loop, cluster_name):
+    def __init__(self, dts, log, loop, project, cluster_name):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._cluster_name = cluster_name
 
         self._vcs_handler = VcsComponentDtsHandler(dts, log, loop, self)
         self._vnfr_handler = VnfrDtsHandler(dts, log, loop, self)
         self._vnfr_ref_handler = VnfdRefCountDtsHandler(dts, log, loop, self)
-        self._nsr_handler = mano_dts.NsInstanceConfigSubscriber(log, dts, loop, callback=self.handle_nsr)
+        self._nsr_handler = mano_dts.NsInstanceConfigSubscriber(
+            log, dts, loop, project, callback=self.handle_nsr)
 
         self._dts_handlers = [VnfdDtsHandler(dts, log, loop, self),
                               self._vnfr_handler,
@@ -2542,6 +2618,11 @@
         for hdl in self._dts_handlers:
             yield from hdl.register()
 
+    def deregister(self):
+        self.log.debug("De-register VNFM project {}".format(self.name))
+        for hdl in self._dts_handlers:
+            yield from hdl.deregister()
+
     @asyncio.coroutine
     def run(self):
         """ Run this VNFM instance """
@@ -2627,11 +2708,13 @@
     @asyncio.coroutine
     def fetch_vnfd(self, vnfd_id):
         """ Fetch VNFDs based with the vnfd id"""
-        vnfd_path = VirtualNetworkFunctionRecord.vnfd_xpath(vnfd_id)
+        vnfd_path = self._project.add_project(
+            VirtualNetworkFunctionRecord.vnfd_xpath(vnfd_id))
         self._log.debug("Fetch vnfd with path %s", vnfd_path)
         vnfd = None
 
-        res_iter = yield from self._dts.query_read(vnfd_path, rwdts.XactFlag.MERGE)
+        res_iter = yield from self._dts.query_read(vnfd_path,
+                                                   rwdts.XactFlag.MERGE)
 
         for ent in res_iter:
             res = yield from ent
@@ -2690,8 +2773,8 @@
 
     def vnfd_refcount_xpath(self, vnfd_id):
         """ xpath for ref count entry """
-        return (VnfdRefCountDtsHandler.XPATH +
-                "[rw-vnfr:vnfd-id-ref = '{}']").format(vnfd_id)
+        return self._project.add_project(VnfdRefCountDtsHandler.XPATH +
+                                         "[rw-vnfr:vnfd-id-ref = '{}']").format(vnfd_id)
 
     @asyncio.coroutine
     def get_vnfd_refcount(self, vnfd_id):
@@ -2699,12 +2782,12 @@
         vnfd_list = []
         if vnfd_id is None or vnfd_id == "":
             for vnfd in self._vnfds_to_vnfr.keys():
-                vnfd_msg = RwVnfrYang.YangData_Vnfr_VnfrCatalog_VnfdRefCount()
+                vnfd_msg = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_VnfdRefCount()
                 vnfd_msg.vnfd_id_ref = vnfd
                 vnfd_msg.instance_ref_count = self._vnfds_to_vnfr[vnfd]
                 vnfd_list.append((self.vnfd_refcount_xpath(vnfd), vnfd_msg))
         elif vnfd_id in self._vnfds_to_vnfr:
-                vnfd_msg = RwVnfrYang.YangData_Vnfr_VnfrCatalog_VnfdRefCount()
+                vnfd_msg = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_VnfdRefCount()
                 vnfd_msg.vnfd_id_ref = vnfd_id
                 vnfd_msg.instance_ref_count = self._vnfds_to_vnfr[vnfd_id]
                 vnfd_list.append((self.vnfd_refcount_xpath(vnfd_id), vnfd_msg))
@@ -2712,6 +2795,31 @@
         return vnfd_list
 
 
+class VnfmProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(VnfmProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self._vnfm = None
+
+    @asyncio.coroutine
+    def register (self):
+        try:
+            vm_parent_name = self._tasklet.tasklet_info.get_parent_vm_parent_instance_name()
+            assert vm_parent_name is not None
+            self._vnfm = VnfManager(self._dts, self.log, self.loop, self, vm_parent_name)
+            yield from self._vnfm.run()
+        except Exception:
+            print("Caught Exception in VNFM init:", sys.exc_info()[0])
+            raise
+
+    def deregister(self):
+        self._log.debug("De-register project {} for VnfmProject".
+                        format(self.name))
+        self._vnfm.deregister()
+
+
 class VnfmTasklet(rift.tasklets.Tasklet):
     """ VNF Manager tasklet class """
     def __init__(self, *args, **kwargs):
@@ -2720,7 +2828,12 @@
         self.rwlog.set_subcategory("vnfm")
 
         self._dts = None
-        self._vnfm = None
+        self._project_handler = None
+        self.projects = {}
+
+    @property
+    def dts(self):
+        return self._dts
 
     def start(self):
         try:
@@ -2754,14 +2867,9 @@
     @asyncio.coroutine
     def init(self):
         """ Task init callback """
-        try:
-            vm_parent_name = self.tasklet_info.get_parent_vm_parent_instance_name()
-            assert vm_parent_name is not None
-            self._vnfm = VnfManager(self._dts, self.log, self.loop, vm_parent_name)
-            yield from self._vnfm.run()
-        except Exception:
-            print("Caught Exception in VNFM init:", sys.exc_info()[0])
-            raise
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, VnfmProject)
+        self.project_handler.register()
 
     @asyncio.coroutine
     def run(self):
diff --git a/rwlaunchpad/plugins/rwvns/rift/tasklets/rwvnstasklet/rwvnstasklet.py b/rwlaunchpad/plugins/rwvns/rift/tasklets/rwvnstasklet/rwvnstasklet.py
index 9ec6764..1720e39 100755
--- a/rwlaunchpad/plugins/rwvns/rift/tasklets/rwvnstasklet/rwvnstasklet.py
+++ b/rwlaunchpad/plugins/rwvns/rift/tasklets/rwvnstasklet/rwvnstasklet.py
@@ -32,6 +32,10 @@
 )
 
 import rift.tasklets
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+)
 
 from rift.vlmgr import (
     VlrDtsHandler,
@@ -79,13 +83,16 @@
         self._log = log
         self._loop = loop
         self._parent = parent
+        self._project = self._parent._project
+        self._regh = None
+        self._rpch = None
 
     def _register_show_status(self):
         def get_xpath(sdn_name=None):
-            return "D,/rw-project:project/rw-sdn:sdn/rw-sdn:account{}" \
+            return self._project.add_project("D,/rw-sdn:sdn/rw-sdn:account{}" \
                 "/rw-sdn:connection-status".format(
                     "[name='%s']" % sdn_name if sdn_name is not None else ''
-                   )
+                   ))
 
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
@@ -112,12 +119,12 @@
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
-        yield from self._dts.register(
-                xpath=get_xpath(),
-                handler=rift.tasklets.DTS.RegistrationHandler(
-                    on_prepare=on_prepare),
-                flags=rwdts.Flag.PUBLISHER,
-                )
+        self._regh = yield from self._dts.register(
+            xpath=get_xpath(),
+            handler=rift.tasklets.DTS.RegistrationHandler(
+                on_prepare=on_prepare),
+            flags=rwdts.Flag.PUBLISHER,
+        )
 
     def _register_validate_rpc(self):
         def get_xpath():
@@ -125,6 +132,10 @@
 
         @asyncio.coroutine
         def on_prepare(xact_info, action, ks_path, msg):
+
+            if not self._project.rpc_check(msg, xact_info=xact_info):
+                return
+
             if not msg.has_field("sdn_account"):
                 raise SdnAccountNotFound("SDN account name not provided")
 
@@ -139,28 +150,46 @@
 
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
-        yield from self._dts.register(
-                xpath=get_xpath(),
-                handler=rift.tasklets.DTS.RegistrationHandler(
-                    on_prepare=on_prepare
-                    ),
-                flags=rwdts.Flag.PUBLISHER,
-                )
+        self._rpch = yield from self._dts.register(
+            xpath=get_xpath(),
+            handler=rift.tasklets.DTS.RegistrationHandler(
+                on_prepare=on_prepare
+            ),
+            flags=rwdts.Flag.PUBLISHER,
+        )
 
     @asyncio.coroutine
     def register(self):
         yield from self._register_show_status()
         yield from self._register_validate_rpc()
 
+    def deregister(self):
+        self._log.debug("De-register SDN opdata handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
+        if self._rpch:
+            self._rpch.deregister()
+            self._rpch = None
+
+
 class SDNAccountDtsHandler(object):
-    XPATH = "C,/rw-project:project/rw-sdn:sdn/rw-sdn:account"
+    XPATH = "C,/rw-sdn:sdn/rw-sdn:account"
 
     def __init__(self, dts, log, parent):
         self._dts = dts
         self._log = log
         self._parent = parent
+        self._project = parent._project
 
         self._sdn_account = {}
+        self._regh = None
+
+    @property
+    def _xpath(self):
+        return self._project.add_project(SDNAccountDtsHandler.XPATH)
 
     def _set_sdn_account(self, account):
         self._log.info("Setting sdn account: {}".format(account))
@@ -211,7 +240,7 @@
                         errmsg = "Cannot update SDN account's account-type."
                         self._log.error(errmsg)
                         xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
-                                                   SDNAccountDtsHandler.XPATH,
+                                                   self._xpath,
                                                    errmsg)
                         raise SdnAccountError(errmsg)
 
@@ -223,7 +252,7 @@
                         errmsg = "New SDN account must contain account-type field."
                         self._log.error(errmsg)
                         xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
-                                                   SDNAccountDtsHandler.XPATH,
+                                                   self._xpath,
                                                    errmsg)
                         raise SdnAccountError(errmsg)
 
@@ -233,37 +262,47 @@
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
 
 
-        self._log.debug("Registering for Sdn Account config using xpath: %s",
-                        SDNAccountDtsHandler.XPATH,
-                        )
+        self._log.debug("Registering for Sdn Account config using xpath: {}".
+                        format(self._xpath))
 
         acg_handler = rift.tasklets.AppConfGroup.Handler(
                         on_apply=apply_config,
                         )
 
         with self._dts.appconf_group_create(acg_handler) as acg:
-            acg.register(
-                    xpath=SDNAccountDtsHandler.XPATH,
-                    flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
-                    on_prepare=on_prepare
-                    )
+            self._regh = acg.register(
+                xpath=self._xpath,
+                flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY,
+                on_prepare=on_prepare
+            )
+
+    def deregister(self):
+        self._log.debug("De-register VLR handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
 
 
 class VnsManager(object):
     """ The Virtual Network Service Manager """
-    def __init__(self, dts, log, log_hdl, loop):
+    def __init__(self, dts, log, log_hdl, loop, project):
         self._dts = dts
         self._log = log
         self._log_hdl = log_hdl
         self._loop = loop
+        self._project = project
+
         self._vlr_handler = VlrDtsHandler(dts, log, loop, self)
         self._vld_handler = VldDtsHandler(dts, log, loop, self)
         self._sdn_handler = SDNAccountDtsHandler(dts,log,self)
         self._sdn_opdata_handler = SDNAccountDtsOperdataHandler(dts,log, loop, self)
-        self._acctmgr = SdnAccountMgr(self._log, self._log_hdl, self._loop)
+        self._acctmgr = SdnAccountMgr(self._log, self._log_hdl, self._loop, self._project)
         self._nwtopdata_store = NwtopDataStore(log)
-        self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, self._acctmgr, self._nwtopdata_store)
-        self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, self._acctmgr, self._nwtopdata_store)
+        self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, self._project,
+                                                                self._acctmgr, self._nwtopdata_store)
+        self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, self._project,
+                                                          self._acctmgr, self._nwtopdata_store)
         self._vlrs = {}
 
     @asyncio.coroutine
@@ -307,6 +346,14 @@
         # Not used for now
         yield from self.register_nwtopdiscovery_handler()
 
+    def deregister(self):
+        self._nwtopdiscovery_handler.deregister()
+        self._nwtopstatic_handler.deregister()
+        self._vld_handler.deregister()
+        self._vlr_handler.deregister()
+        self._sdn_opdata_handler.deregister()
+        self._sdn_handler.deregister()
+
     def create_vlr(self, msg):
         """ Create VLR """
         if msg.id in self._vlrs:
@@ -360,19 +407,52 @@
         return False
 
     @asyncio.coroutine
-    def publish_vlr(self, xact, path, msg):
+    def publish_vlr(self, xact, xpath, msg):
         """ Publish a VLR """
+        path = self._project.add_project(xpath)
         self._log.debug("Publish vlr called with path %s, msg %s",
                         path, msg)
         yield from self._vlr_handler.update(xact, path, msg)
 
     @asyncio.coroutine
-    def unpublish_vlr(self, xact, path):
+    def unpublish_vlr(self, xact, xpath):
         """ Publish a VLR """
+        path = self._project.add_project(xpath)
         self._log.debug("Unpublish vlr called with path %s", path)
         yield from self._vlr_handler.delete(xact, path)
 
 
+class VnsProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(VnsProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self._vlr_handler = None
+        self._vnsm = None
+        # A mapping of instantiated vlr_id's to VirtualLinkRecord objects
+        self._vlrs = {}
+
+    @asyncio.coroutine
+    def register (self):
+        self._vnsm = VnsManager(dts=self._dts,
+                                log=self.log,
+                                log_hdl=self._log_hdl,
+                                loop=self._loop,
+                                project=self)
+        yield from self._vnsm.run()
+
+        # NSM needs to detect VLD deletion that has active VLR
+        # self._vld_handler = VldDescriptorConfigDtsHandler(
+        #         self._dts, self.log, self.loop, self._vlrs,
+        #         )
+        # yield from self._vld_handler.register()
+
+    def deregister(self):
+        self._log.debug("De-register project {}".format(self.name))
+        self._vnsm.deregister()
+
+
 class VnsTasklet(rift.tasklets.Tasklet):
     """ The VNS tasklet class """
     def __init__(self, *args, **kwargs):
@@ -381,11 +461,12 @@
         self.rwlog.set_subcategory("vns")
 
         self._dts = None
-        self._vlr_handler = None
+        self._project_handler = None
+        self.projects = {}
 
-        self._vnsm = None
-        # A mapping of instantiated vlr_id's to VirtualLinkRecord objects
-        self._vlrs = {}
+    @property
+    def dts(self):
+        return self._dts
 
     def start(self):
         super(VnsTasklet, self).start()
@@ -413,17 +494,9 @@
     @asyncio.coroutine
     def init(self):
         """ task init callback"""
-        self._vnsm = VnsManager(dts=self._dts,
-                                log=self.log,
-                                log_hdl=self.log_hdl,
-                                loop=self.loop)
-        yield from self._vnsm.run()
-
-        # NSM needs to detect VLD deletion that has active VLR
-        # self._vld_handler = VldDescriptorConfigDtsHandler(
-        #         self._dts, self.log, self.loop, self._vlrs,
-        #         )
-        # yield from self._vld_handler.register()
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, VnsProject)
+        self.project_handler.register()
 
     @asyncio.coroutine
     def run(self):
diff --git a/rwlaunchpad/plugins/rwvns/rift/topmgr/rwtopmgr.py b/rwlaunchpad/plugins/rwvns/rift/topmgr/rwtopmgr.py
index b095fbc..e1c7ea1 100755
--- a/rwlaunchpad/plugins/rwvns/rift/topmgr/rwtopmgr.py
+++ b/rwlaunchpad/plugins/rwvns/rift/topmgr/rwtopmgr.py
@@ -39,8 +39,8 @@
 class SdnGetPluginError(Exception):
     """ Error while fetching SDN plugin """
     pass
-  
-  
+
+
 class SdnGetInterfaceError(Exception):
     """ Error while fetching SDN interface"""
     pass
@@ -48,16 +48,17 @@
 
 class SdnAccountMgr(object):
     """ Implements the interface to backend plugins to fetch topology """
-    def __init__(self, log, log_hdl, loop):
+    def __init__(self, log, log_hdl, loop, project):
         self._account = {}
         self._log = log
         self._log_hdl = log_hdl
         self._loop = loop
+        self._project = project
         self._sdn = {}
 
         self._regh = None
 
-        self._status = RwsdnYang.SDNAccount_ConnectionStatus(
+        self._status = RwsdnYang.SdnConnectionStatus(
                 status='unknown',
                 details="Connection status lookup not started"
                 )
@@ -160,9 +161,9 @@
                 )
 
         if rwstatus == RwTypes.RwStatus.SUCCESS:
-            self._status = RwsdnYang.SDNAccount_ConnectionStatus.from_dict(status.as_dict())
+            self._status = RwsdnYang.SdnConnectionStatus.from_dict(status.as_dict())
         else:
-            self._status = RwsdnYang.SDNAccount_ConnectionStatus(
+            self._status = RwsdnYang.SdnConnectionStatus(
                     status="failure",
                     details="Error when calling CAL validate sdn creds"
                     )
@@ -185,10 +186,11 @@
     """ Handles DTS interactions for the Discovered Topology registration """
     DISC_XPATH = "D,/nd:network"
 
-    def __init__(self, dts, log, loop, acctmgr, nwdatastore):
+    def __init__(self, dts, log, loop, project, acctmgr, nwdatastore):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._acctmgr = acctmgr
         self._nwdatastore = nwdatastore
 
@@ -199,6 +201,13 @@
         """ The registration handle associated with this Handler"""
         return self._regh
 
+    def deregister(self):
+        self._log.debug("De-register Topology discovery handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Register for the Discovered Topology path """
@@ -268,10 +277,11 @@
     """ Handles DTS interactions for the Static Topology registration """
     STATIC_XPATH = "C,/nd:network"
 
-    def __init__(self, dts, log, loop, acctmgr, nwdatastore):
+    def __init__(self, dts, log, loop, project, acctmgr, nwdatastore):
         self._dts = dts
         self._log = log
         self._loop = loop
+        self._project = project
         self._acctmgr = acctmgr
 
         self._regh = None
@@ -282,8 +292,14 @@
     def regh(self):
         """ The registration handle associated with this Handler"""
         return self._regh
- 
-    
+
+    def deregister(self):
+        self._log.debug("De-register Topology static handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
     def register(self):
         """ Register for the Static Topology path """
@@ -322,8 +338,6 @@
                         on_apply=apply_nw_config)
 
         with self._dts.appconf_group_create(handler=handler) as acg:
-            acg.register(xpath = NwtopStaticDtsHandler.STATIC_XPATH, 
-                                   flags = rwdts.Flag.SUBSCRIBER, 
-                                   on_prepare=prepare_nw_cfg)
-
-
+            self._regh = acg.register(xpath = NwtopStaticDtsHandler.STATIC_XPATH,
+                                      flags = rwdts.Flag.SUBSCRIBER,
+                                      on_prepare=prepare_nw_cfg)
diff --git a/rwlaunchpad/plugins/rwvns/rift/vlmgr/rwvlmgr.py b/rwlaunchpad/plugins/rwvns/rift/vlmgr/rwvlmgr.py
index bdea4ef..8fc267e 100755
--- a/rwlaunchpad/plugins/rwvns/rift/vlmgr/rwvlmgr.py
+++ b/rwlaunchpad/plugins/rwvns/rift/vlmgr/rwvlmgr.py
@@ -70,6 +70,7 @@
         self._vnsm = vnsm
         self._vlr_msg = vlr_msg
 
+        self._project = vnsm._project
         self._network_id = None
         self._network_pool = None
         self._assigned_subnet = None
@@ -85,7 +86,8 @@
     @property
     def vld_xpath(self):
         """ VLD xpath associated with this VLR record """
-        return "C,/vld:vld-catalog/vld:vld[id='{}']".format(self.vld_id)
+        return self._project.add_project("C,/vld:vld-catalog/vld:vld[id='{}']".
+                                         format(self.vld_id))
 
     @property
     def vld_id(self):
@@ -100,7 +102,7 @@
     @property
     def xpath(self):
         """ path for this VLR """
-        return("D,/vlr:vlr-catalog"
+        return self._project.add_project("D,/vlr:vlr-catalog"
                "/vlr:vlr[vlr:id='{}']".format(self.vlr_id))
 
     @property
@@ -116,7 +118,7 @@
     @property
     def resmgr_path(self):
         """ path for resource-mgr"""
-        return ("D,/rw-resource-mgr:resource-mgmt" +
+        return self._project.add_project("D,/rw-resource-mgr:resource-mgmt" +
                 "/vlink-event/vlink-event-data[event-id='{}']".format(self._request_id))
 
     @property
@@ -135,7 +137,7 @@
     @property
     def msg(self):
         """ VLR message for this VLR """
-        msg = RwVlrYang.YangData_Vlr_VlrCatalog_Vlr()
+        msg = RwVlrYang.YangData_RwProject_Project_VlrCatalog_Vlr()
         msg.copy_from(self._vlr_msg)
 
         if self._network_id is not None:
@@ -313,6 +315,7 @@
         self._vnsm = vnsm
 
         self._regh = None
+        self._project = vnsm._project
 
     @property
     def regh(self):
@@ -369,7 +372,7 @@
                 return
             elif action == rwdts.QueryAction.DELETE:
                 # Delete an VLR record
-                schema = RwVlrYang.YangData_Vlr_VlrCatalog_Vlr.schema()
+                schema = RwVlrYang.YangData_RwProject_Project_VlrCatalog_Vlr.schema()
                 path_entry = schema.keyspec_to_entry(ks_path)
                 self._log.debug("Terminating VLR id %s", path_entry.key00.id)
                 yield from self._vnsm.delete_vlr(path_entry.key00.id, xact_info.xact)
@@ -379,8 +382,9 @@
             xact_info.respond_xpath(rwdts.XactRspCode.ACK)
             return
 
-        self._log.debug("Registering for VLR using xpath: %s",
-                        VlrDtsHandler.XPATH)
+        xpath = self._project.add_project(VlrDtsHandler.XPATH)
+        self._log.debug("Registering for VLR using xpath: {}".
+                        format(xpath))
 
         reg_handle = rift.tasklets.DTS.RegistrationHandler(
             on_commit=on_commit,
@@ -389,16 +393,24 @@
         handlers = rift.tasklets.Group.Handler(on_event=on_event,)
         with self._dts.group_create(handler=handlers) as group:
             self._regh = group.register(
-                xpath=VlrDtsHandler.XPATH,
+                xpath=xpath,
                 handler=reg_handle,
                 flags=rwdts.Flag.PUBLISHER | rwdts.Flag.NO_PREP_READ| rwdts.Flag.DATASTORE,
                 )
 
+    def deregister(self):
+        self._log.debug("De-register VLR handler for project {}".
+                        format(self._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
+
     @asyncio.coroutine
-    def create(self, xact, path, msg):
+    def create(self, xact, xpath, msg):
         """
         Create a VLR record in DTS with path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Creating VLR xact = %s, %s:%s",
                         xact, path, msg)
         self.regh.create_element(path, msg)
@@ -406,10 +418,11 @@
                         xact, path, msg)
 
     @asyncio.coroutine
-    def update(self, xact, path, msg):
+    def update(self, xact, xpath, msg):
         """
         Update a VLR record in DTS with path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Updating VLR xact = %s, %s:%s",
                         xact, path, msg)
         self.regh.update_element(path, msg)
@@ -417,10 +430,11 @@
                         xact, path, msg)
 
     @asyncio.coroutine
-    def delete(self, xact, path):
+    def delete(self, xact, xpath):
         """
         Delete a VLR record in DTS with path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Deleting VLR xact = %s, %s", xact, path)
         self.regh.delete_element(path)
         self._log.debug("Deleted VLR xact = %s, %s", xact, path)
@@ -453,8 +467,13 @@
                 "Got on prepare for VLD update (ks_path: %s) (action: %s)",
                 ks_path.to_xpath(VldYang.get_schema()), msg)
 
-            schema = VldYang.YangData_Vld_VldCatalog_Vld.schema()
+            schema = VldYang.YangData_RwProject_Project_VldCatalog_Vld.schema()
             path_entry = schema.keyspec_to_entry(ks_path)
+            # TODO: Check why on project delete this gets called
+            if not path_entry:
+                xact_info.respond_xpath(rwdts.XactRspCode.ACK)
+                return
+
             vld_id = path_entry.key00.id
 
             disabled_actions = [rwdts.QueryAction.DELETE, rwdts.QueryAction.UPDATE]
@@ -477,7 +496,14 @@
         handler = rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare)
 
         yield from self._dts.register(
-            VldDtsHandler.XPATH,
+            self._vnsm._project.add_project(VldDtsHandler.XPATH),
             flags=rwdts.Flag.SUBSCRIBER,
             handler=handler
             )
+
+    def deregister(self):
+        self._log.debug("De-register VLD handler for project {}".
+                        format(self._vnsm._project.name))
+        if self._regh:
+            self._regh.deregister()
+            self._regh = None
diff --git a/rwlaunchpad/plugins/yang/rw-pkg-mgmt.yang b/rwlaunchpad/plugins/yang/rw-pkg-mgmt.yang
index 5c68f00..747fbc5 100644
--- a/rwlaunchpad/plugins/yang/rw-pkg-mgmt.yang
+++ b/rwlaunchpad/plugins/yang/rw-pkg-mgmt.yang
@@ -260,6 +260,7 @@
         description "Valid ID to track the status of the task";
         type string;
       }
+      uses manotypes:rpc-project-name;
     }
   }
 
@@ -277,6 +278,7 @@
         description "Valid ID to track the status of the task";
         type string;
       }
+      uses manotypes:rpc-project-name;
     }
   }
 
@@ -316,6 +318,8 @@
         description "Valid ID to track the status of the task";
         type string;
       }
+
+      uses manotypes:rpc-project-name;
     }
   }
 
@@ -333,6 +337,7 @@
         description "Valid ID to track the status of the task";
         type string;
       }
+      uses manotypes:rpc-project-name;
     }
   }
 
@@ -354,6 +359,8 @@
         description "Trace in case of a failure";
         type string;
       }
+
+      uses manotypes:rpc-project-name;
     }
   }
 
diff --git a/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_slb.py b/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_slb.py
index 557518b..fb4bd61 100755
--- a/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_slb.py
+++ b/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_slb.py
@@ -71,7 +71,7 @@
     Return:
          NSR object
     """
-    nsr = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
 
     nsr.id = str(uuid.uuid4())
     nsr.name = rift.auto.mano.resource_name(nsr.id)
@@ -210,11 +210,11 @@
         nsd = catalog.nsd[0]
 
         input_parameters = []
-        descr_xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
+        descr_xpath = "/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
         descr_value = "New NSD Description"
         in_param_id = str(uuid.uuid4())
 
-        input_param_1= NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
+        input_param_1= NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
                                                                 xpath=descr_xpath,
                                                                 value=descr_value)
 
diff --git a/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_trafgen.py b/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_trafgen.py
index ca6e9b5..b05a23c 100755
--- a/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_trafgen.py
+++ b/rwlaunchpad/ra/pytest/multivm_vnf/test_multi_vm_vnf_trafgen.py
@@ -78,7 +78,7 @@
     Return:
          NSR object
     """
-    nsr = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
 
     nsr.id = str(uuid.uuid4())
     nsr.name = rift.auto.mano.resource_name(nsr.id)
@@ -206,11 +206,11 @@
         nsd = catalog.nsd[0]
 
         input_parameters = []
-        descr_xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
+        descr_xpath = "/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
         descr_value = "New NSD Description"
         in_param_id = str(uuid.uuid4())
 
-        input_param_1= NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
+        input_param_1= NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
                                                                 xpath=descr_xpath,
                                                                 value=descr_value)
 
diff --git a/rwlaunchpad/ra/pytest/ns/haproxy/test_scaling.py b/rwlaunchpad/ra/pytest/ns/haproxy/test_scaling.py
index 846ef2e..3cf2c52 100644
--- a/rwlaunchpad/ra/pytest/ns/haproxy/test_scaling.py
+++ b/rwlaunchpad/ra/pytest/ns/haproxy/test_scaling.py
@@ -25,8 +25,8 @@
     return mgmt_session.proxy
 
 
-ScalingGroupInstance = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup_Instance
-ScalingGroup = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup
+ScalingGroupInstance = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup_Instance
+ScalingGroup = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup
 
 INSTANCE_ID = 1
 
diff --git a/rwlaunchpad/ra/pytest/ns/pingpong/test_pingpong.py b/rwlaunchpad/ra/pytest/ns/pingpong/test_pingpong.py
index 45a7832..ef4949c 100644
--- a/rwlaunchpad/ra/pytest/ns/pingpong/test_pingpong.py
+++ b/rwlaunchpad/ra/pytest/ns/pingpong/test_pingpong.py
@@ -98,7 +98,7 @@
     Return:
          NSR object
     """
-    nsr = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
 
     nsr.id = str(uuid.uuid4())
     nsr.name = rift.auto.mano.resource_name(nsr.id)
@@ -409,11 +409,11 @@
         nsd = catalog.nsd[0]
 
         input_parameters = []
-        descr_xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:vendor" % nsd.id
+        descr_xpath = "/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:vendor" % nsd.id
         descr_value = "automation"
         in_param_id = str(uuid.uuid4())
 
-        input_param_1 = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
+        input_param_1 = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
                                                                 xpath=descr_xpath,
                                                                 value=descr_value)
 
@@ -597,11 +597,11 @@
         nsd = catalog.nsd[0]
 
         input_parameters = []
-        descr_xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:vendor" % nsd.id
+        descr_xpath = "/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:vendor" % nsd.id
         descr_value = "automation"
         in_param_id = str(uuid.uuid4())
 
-        input_param_1 = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
+        input_param_1 = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
                                                                 xpath=descr_xpath,
                                                                 value=descr_value)
 
diff --git a/rwlaunchpad/ra/pytest/ns/test_onboard.py b/rwlaunchpad/ra/pytest/ns/test_onboard.py
index 5951ce8..ecec834 100644
--- a/rwlaunchpad/ra/pytest/ns/test_onboard.py
+++ b/rwlaunchpad/ra/pytest/ns/test_onboard.py
@@ -99,7 +99,7 @@
     Return:
          NSR object
     """
-    nsr = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
 
     nsr.id = str(uuid.uuid4())
     nsr.name = rift.auto.mano.resource_name(nsr.id)
@@ -333,11 +333,11 @@
         nsd = catalog.nsd[0]
 
         input_parameters = []
-        descr_xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
+        descr_xpath = "/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
         descr_value = "New NSD Description"
         in_param_id = str(uuid.uuid4())
 
-        input_param_1 = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
+        input_param_1 = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
                                                                 xpath=descr_xpath,
                                                                 value=descr_value)
 
diff --git a/rwlaunchpad/test/mano_error_ut.py b/rwlaunchpad/test/mano_error_ut.py
index e593cee..0790290 100755
--- a/rwlaunchpad/test/mano_error_ut.py
+++ b/rwlaunchpad/test/mano_error_ut.py
@@ -174,8 +174,8 @@
 
 
 class ResourceMgrMock(object):
-    VDU_REQUEST_XPATH = "D,/rw-resource-mgr:resource-mgmt/vdu-event/vdu-event-data"
-    VLINK_REQUEST_XPATH = "D,/rw-resource-mgr:resource-mgmt/vlink-event/vlink-event-data"
+    VDU_REQUEST_XPATH = "D,/rw-project:project/rw-resource-mgr:resource-mgmt/vdu-event/vdu-event-data"
+    VLINK_REQUEST_XPATH = "D,/rw-project:project/rw-resource-mgr:resource-mgmt/vlink-event/vlink-event-data"
 
     def __init__(self, dts, log, loop):
         self._log = log
diff --git a/rwlaunchpad/test/mano_ut.py b/rwlaunchpad/test/mano_ut.py
index 1482ec3..3835ab5 100755
--- a/rwlaunchpad/test/mano_ut.py
+++ b/rwlaunchpad/test/mano_ut.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 
-# 
+#
 #   Copyright 2016-2017 RIFT.IO Inc
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
@@ -57,8 +57,14 @@
 import rift.tasklets
 import rift.test.dts
 import rw_peas
+from rift.mano.utils.project import (
+    ManoProject,
+    DEFAULT_PROJECT,
+)
 
 
+PROJECT = 'default'
+
 openstack_info = {
         'username': 'pluto',
         'password': 'mypasswd',
@@ -125,11 +131,8 @@
 
     @staticmethod
     def cm_state(k=None):
-        if k is None:
-            return ("D,/rw-conman:cm-state/rw-conman:cm-nsr")
-        else:
-            return ("D,/rw-conman:cm-state/rw-conman:cm-nsr" +
-                    ("[rw-conman:id='{}']".format(k) if k is not None else ""))
+        return ("D,/rw-conman:cm-state/rw-conman:cm-nsr" +
+                ("[rw-conman:id='{}']".format(k) if k is not None else ""))
 
     @staticmethod
     def nsr_scale_group_instance(nsr_id=None, group_name=None, index=None):
@@ -149,19 +152,37 @@
                 ("/nsr:instance") +
                 ("[nsr:index='{}']".format(index) if index is not None else ""))
 
+    @staticmethod
+    def cloud_account(k=None):
+        return ("C,/rw-cloud:cloud/rw-cloud:account" +
+                ("[rw-cloud:name='{}']".format(k) if k is not None else ""))
+
+    @staticmethod
+    def project(k=None):
+        return ("C,/rw-project:project" +
+                ("[rw-project:name='{}']".format(k) if k is not None else ""))
+
 
 class ManoQuerier(object):
-    def __init__(self, log, dts):
+    def __init__(self, log, dts, project):
         self.log = log
         self.dts = dts
+        self.project = project
+
+    def add_project(self, xpath):
+        return self.project.add_project(xpath)
 
     @asyncio.coroutine
-    def _read_query(self, xpath, do_trace=False):
-        self.log.debug("Running XPATH read query: %s (trace: %s)", xpath, do_trace)
+    def _read_query(self, xpath, do_trace=False, project=True):
+        if project:
+            xp = self.add_project(xpath)
+        else:
+            xp = xpath
+        self.log.debug("Running XPATH read query: %s (trace: %s)", xp, do_trace)
         flags = rwdts.XactFlag.MERGE
         flags += rwdts.XactFlag.TRACE if do_trace else 0
         res_iter = yield from self.dts.query_read(
-                xpath, flags=flags
+                xp, flags=flags
                 )
 
         results = []
@@ -173,6 +194,27 @@
         return results
 
     @asyncio.coroutine
+    def _delete_query(self, xpath, flags=0):
+        xp = self.add_project(xpath)
+        self.log.debug("Running XPATH delete query: %s (flags: %d)", xp, flags)
+        with self.dts.transaction() as xact:
+            yield from self.dts.query_delete(
+                xp,
+                flags
+            )
+
+    @asyncio.coroutine
+    def _update_query(self, xpath, msg, flags=0):
+        xp = self.add_project(xpath)
+        self.log.debug("Running XPATH update query: %s (flags: %d)", xp, flags)
+        with self.dts.transaction() as xact:
+            yield from self.dts.query_update(
+                xp,
+                flags,
+                msg
+            )
+
+    @asyncio.coroutine
     def get_cm_state(self, nsr_id=None):
         return (yield from self._read_query(XPaths.cm_state(nsr_id), False))
 
@@ -183,7 +225,6 @@
     @asyncio.coroutine
     def get_nsr_scale_group_instance_opdata(self, nsr_id=None, group_name=None, index=None):
         return (yield from self._read_query(XPaths.nsr_scale_group_instance(nsr_id, group_name, index), False))
-        #return (yield from self._read_query(XPaths.nsr_scale_group_instance(nsr_id, group_name), True))
 
     @asyncio.coroutine
     def get_nsr_configs(self, nsr_id=None):
@@ -211,66 +252,34 @@
 
     @asyncio.coroutine
     def delete_nsr(self, nsr_id):
-        with self.dts.transaction() as xact:
-            yield from self.dts.query_delete(
-                    XPaths.nsr_config(nsr_id),
-                    0
-                    #rwdts.XactFlag.TRACE,
-                    #rwdts.Flag.ADVISE,
-                    )
+        return (yield from self._delete_query(XPaths.nsr_config(nsr_id)))
 
     @asyncio.coroutine
     def delete_nsd(self, nsd_id):
-        nsd_xpath = XPaths.nsd(nsd_id)
-        self.log.debug("Attempting to delete NSD with path = %s", nsd_xpath)
-        with self.dts.transaction() as xact:
-            yield from self.dts.query_delete(
-                    nsd_xpath,
-                    rwdts.XactFlag.ADVISE,
-                    )
+        return (yield from self._delete_query(XPaths.nsd(nsd_id),
+                                              rwdts.XactFlag.ADVISE))
 
     @asyncio.coroutine
     def delete_vnfd(self, vnfd_id):
-        vnfd_xpath = XPaths.vnfd(vnfd_id)
-        self.log.debug("Attempting to delete VNFD with path = %s", vnfd_xpath)
-        with self.dts.transaction() as xact:
-            yield from self.dts.query_delete(
-                    vnfd_xpath,
-                    rwdts.XactFlag.ADVISE,
-                    )
+        return (yield from self._delete_query(XPaths.vnfd(vnfd_id),
+                                              rwdts.XactFlag.ADVISE))
 
     @asyncio.coroutine
     def update_nsd(self, nsd_id, nsd_msg):
-        nsd_xpath = XPaths.nsd(nsd_id)
-        self.log.debug("Attempting to update NSD with path = %s", nsd_xpath)
-        with self.dts.transaction() as xact:
-            yield from self.dts.query_update(
-                    nsd_xpath,
-                    rwdts.XactFlag.ADVISE,
-                    nsd_msg,
-                    )
+        return (yield from self._update_query(XPaths.nsd(nsd_id), nsd_msg,
+                                              rwdts.XactFlag.ADVISE))
 
     @asyncio.coroutine
     def update_vnfd(self, vnfd_id, vnfd_msg):
-        vnfd_xpath = XPaths.vnfd(vnfd_id)
-        self.log.debug("Attempting to delete VNFD with path = %s", vnfd_xpath)
-        with self.dts.transaction() as xact:
-            yield from self.dts.query_update(
-                    vnfd_xpath,
-                    rwdts.XactFlag.ADVISE,
-                    vnfd_msg,
-                    )
+        return (yield from self._update_query(XPaths.vnfd(vnfd_id), vnfd_msg,
+                                              rwdts.XactFlag.ADVISE))
 
     @asyncio.coroutine
     def update_nsr_config(self, nsr_id, nsr_msg):
-        nsr_xpath = XPaths.nsr_config(nsr_id)
-        self.log.debug("Attempting to update NSR with path = %s", nsr_xpath)
-        with self.dts.transaction() as xact:
-            yield from self.dts.query_update(
-                    nsr_xpath,
-                    rwdts.XactFlag.ADVISE|rwdts.XactFlag.REPLACE,
-                    nsr_msg,
-                    )
+        return (yield from self._update_query(
+            XPaths.nsr_config(nsr_id),
+            nsr_msg,
+            rwdts.XactFlag.ADVISE|rwdts.XactFlag.REPLACE))
 
 
 class ManoTestCase(rift.test.dts.AbstractDTSTest):
@@ -370,39 +379,47 @@
         nsd_ref_counts = yield from self.querier.get_nsd_ref_counts(nsd_id)
         self.assertEqual(num_ref, nsd_ref_counts[0].instance_ref_count)
 
+
 class DescriptorPublisher(object):
-    def __init__(self, log, loop, dts):
+    def __init__(self, log, loop, dts, project):
         self.log = log
         self.loop = loop
         self.dts = dts
+        self.project = project
 
         self._registrations = []
 
     @asyncio.coroutine
     def publish(self, w_path, path, desc):
         ready_event = asyncio.Event(loop=self.loop)
+        if 'rw-project' in path:
+            w_xp = w_path
+            xp = path
+        else:
+            w_xp = self.project.add_project(w_path)
+            xp = self.project.add_project(path)
 
         @asyncio.coroutine
         def on_ready(regh, status):
             self.log.debug("Create element: %s, obj-type:%s obj:%s",
-                           path, type(desc), desc)
+                           xp, type(desc), desc)
             with self.dts.transaction() as xact:
-                regh.create_element(path, desc, xact.xact)
-            self.log.debug("Created element: %s, obj:%s", path, desc)
+                regh.create_element(xp, desc, xact.xact)
+            self.log.debug("Created element: %s, obj:%s", xp, desc)
             ready_event.set()
 
         handler = rift.tasklets.DTS.RegistrationHandler(
                 on_ready=on_ready
                 )
 
-        self.log.debug("Registering path: %s, obj:%s", w_path, desc)
+        self.log.debug("Registering path: %s, obj:%s", w_xp, desc)
         reg = yield from self.dts.register(
-                w_path,
+                w_xp,
                 handler,
                 flags=rwdts.Flag.PUBLISHER | rwdts.Flag.NO_PREP_READ
                 )
         self._registrations.append(reg)
-        self.log.debug("Registered path : %s", w_path)
+        self.log.debug("Registered path : %s", w_xp)
         yield from ready_event.wait()
 
         return reg
@@ -413,23 +430,114 @@
             reg.deregister()
 
 
-class PingPongNsrConfigPublisher(object):
-    XPATH = "C,/nsr:ns-instance-config"
+class ProjectPublisher(object):
+    XPATH = "C,/rw-project:project"
 
-    def __init__(self, log, loop, dts, ping_pong, cloud_account_name):
+    def __init__(self, log, loop, dts, project):
         self.dts = dts
         self.log = log
         self.loop = loop
+        self.project = project
         self.ref = None
 
-        self.querier = ManoQuerier(log, dts)
+        self.querier = ManoQuerier(log, dts, project)
+        self.publisher = DescriptorPublisher(log, loop,
+                                             dts, project)
 
-        self.nsr_config = rwnsryang.YangData_Nsr_NsInstanceConfig()
+        self._ready_event = asyncio.Event(loop=self.loop)
+        asyncio.ensure_future(self.register(), loop=loop)
 
-        nsr = rwnsryang.YangData_Nsr_NsInstanceConfig_Nsr()
+    @asyncio.coroutine
+    def register(self):
+        @asyncio.coroutine
+        def on_ready(regh, status):
+            self._ready_event.set()
+
+        self.log.debug("Registering path: %s", ProjectPublisher.XPATH)
+        self.reg = yield from self.dts.register(
+                ProjectPublisher.XPATH,
+                flags=rwdts.Flag.PUBLISHER,
+                handler=rift.tasklets.DTS.RegistrationHandler(
+                    on_ready=on_ready,
+                    ),
+                )
+
+    def deregister(self):
+        if self.reg is not None:
+            self.reg.deregister()
+
+    @asyncio.coroutine
+    def publish_project(self, config, xpath, xpath_wild):
+        # Publish project
+        self.log.debug("Publishing cloud_account path: %s - %s, type:%s, obj:%s",
+                           xpath, xpath_wild, type(config), config)
+        yield from self.publisher.publish(xpath_wild, xpath, config)
+
+
+class CloudAccountPublisher(object):
+    XPATH = "C,/rw-cloud:cloud"
+
+    def __init__(self, log, loop, dts, project):
+        self.dts = dts
+        self.log = log
+        self.loop = loop
+        self.project = project
+        self.ref = None
+
+        self.querier = ManoQuerier(log, dts, project)
+        self.publisher = DescriptorPublisher(log, loop,
+                                             dts, project)
+
+        self.xpath = self.project.add_project(CloudAccountPublisher.XPATH)
+
+        self._ready_event = asyncio.Event(loop=self.loop)
+        asyncio.ensure_future(self.register(), loop=loop)
+
+    @asyncio.coroutine
+    def register(self):
+        @asyncio.coroutine
+        def on_ready(regh, status):
+            self._ready_event.set()
+
+        self.log.debug("Registering path: %s", self.xpath)
+        self.reg = yield from self.dts.register(
+                self.xpath,
+                flags=rwdts.Flag.PUBLISHER,
+                handler=rift.tasklets.DTS.RegistrationHandler(
+                    on_ready=on_ready,
+                    ),
+                )
+
+    def deregister(self):
+        if self.reg is not None:
+            self.reg.deregister()
+
+    @asyncio.coroutine
+    def publish_account(self, account, xpath, xpath_wild):
+        # Publish cloud account
+        self.log.debug("Publishing cloud_account path: %s - %s, type:%s, obj:%s",
+                           xpath, xpath_wild, type(account), account)
+        yield from self.publisher.publish(xpath_wild, xpath, account)
+
+
+class PingPongNsrConfigPublisher(object):
+    XPATH = "C,/nsr:ns-instance-config"
+
+    def __init__(self, log, loop, dts, ping_pong, cloud_account_name, project):
+        self.dts = dts
+        self.log = log
+        self.loop = loop
+        self.project = project
+        self.ref = None
+
+        self.querier = ManoQuerier(log, dts, project)
+        self.xpath = self.project.add_project(PingPongNsrConfigPublisher.XPATH)
+        self.nsr_config = rwnsryang.YangData_RwProject_Project_NsInstanceConfig()
+
+        nsr = rwnsryang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
         nsr.id = str(uuid.uuid4())
         nsr.name = "ns1.{}".format(nsr.id)
-        nsr.nsd = nsryang.YangData_Nsr_NsInstanceConfig_Nsr_Nsd()
+        nsr.nsd = nsryang.YangData_RwProject_Project_NsInstanceConfig_Nsr_Nsd()
         nsr.nsd.from_dict(ping_pong.ping_pong_nsd.nsd.as_dict())
         nsr.cloud_account = cloud_account_name
 
@@ -439,8 +547,9 @@
             #'cloud_account':'mock_account1'
         })
 
-        inputs = nsryang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter()
-        inputs.xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id={}]/nsd:name".format(ping_pong.nsd_id)
+        inputs = nsryang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter()
+        inputs.xpath = self.project.add_project(
+            "/nsd:nsd-catalog/nsd:nsd[nsd:id={}]/nsd:name".format(ping_pong.nsd_id))
         inputs.value = "inigo montoya"
 
         fast_cpu = {'metadata_key': 'FASTCPU', 'metadata_value': 'True'}
@@ -488,9 +597,9 @@
         def on_ready(regh, status):
             self._ready_event.set()
 
-        self.log.debug("Registering path: %s", PingPongNsrConfigPublisher.XPATH)
+        self.log.debug("Registering path: %s", self.xpath)
         self.reg = yield from self.dts.register(
-                PingPongNsrConfigPublisher.XPATH,
+                self.xpath,
                 flags=rwdts.Flag.PUBLISHER,
                 handler=rift.tasklets.DTS.RegistrationHandler(
                     on_ready=on_ready,
@@ -503,7 +612,7 @@
         yield from self._ready_event.wait()
         with self.dts.transaction() as xact:
             self.reg.create_element(
-                    PingPongNsrConfigPublisher.XPATH,
+                    self.xpath,
                     self.nsr_config,
                     xact=xact.xact,
                     )
@@ -520,7 +629,7 @@
             })
         with self.dts.transaction() as xact:
             self.reg.update_element(
-                    PingPongNsrConfigPublisher.XPATH,
+                    self.xpath,
                     self.nsr_config,
                     xact=xact.xact,
                     )
@@ -539,7 +648,7 @@
             "cloud_type"          : cloud_type,
             construct_type        : construct_value,
             })
-        
+
 
     def create_vnfd_placement_group_map(self,
                                         nsr,
@@ -555,21 +664,16 @@
             "cloud_type"           : cloud_type,
             construct_type         : construct_value,
             })
-        
-    
+
+
     @asyncio.coroutine
     def delete_scale_group_instance(self, group_name, index):
         self.log.debug("Deleting scale group %s instance %s", group_name, index)
         #del self.nsr_config.nsr[0].scaling_group[0].instance[0]
-        xpath = XPaths.nsr_scale_group_instance_config(self.nsr_config.nsr[0].id, group_name, index)
+        xpath = self.project.add_project(
+            XPaths.nsr_scale_group_instance_config(self.nsr_config.nsr[0].id,
+                                                   group_name, index))
         yield from self.dts.query_delete(xpath, flags=rwdts.XactFlag.ADVISE)
-        #with self.dts.transaction() as xact:
-        #    self.reg.update_element(
-        #            PingPongNsrConfigPublisher.XPATH,
-        #            self.nsr_config,
-        #            flags=rwdts.XactFlag.REPLACE,
-        #            xact=xact.xact,
-        #            )
 
     def deregister(self):
         if self.reg is not None:
@@ -617,10 +721,12 @@
     def update_vnf_cloud_map(self,vnf_cloud_map):
         self.log.debug("Modifying NSR to add VNF cloud account map: {}".format(vnf_cloud_map))
         for vnf_index,cloud_acct  in vnf_cloud_map.items():
-            vnf_maps = [vnf_map for vnf_map in self.nsr_config.nsr[0].vnf_cloud_account_map if vnf_index == vnf_map.member_vnf_index_ref]
+            vnf_maps = [vnf_map for vnf_map in \
+                        self.nsr_config.nsr[0].vnf_cloud_account_map \
+                        if vnf_index == vnf_map.member_vnf_index_ref]
             if vnf_maps:
                 vnf_maps[0].cloud_account = cloud_acct
-            else: 
+            else:
                 self.nsr_config.nsr[0].vnf_cloud_account_map.add().from_dict({
                     'member_vnf_index_ref':vnf_index,
                     'cloud_account':cloud_acct
@@ -628,13 +734,16 @@
 
 
 class PingPongDescriptorPublisher(object):
-    def __init__(self, log, loop, dts, num_external_vlrs=1, num_internal_vlrs=1, num_ping_vms=1):
+    def __init__(self, log, loop, dts, project,
+                 num_external_vlrs=1, num_internal_vlrs=1, num_ping_vms=1):
         self.log = log
         self.loop = loop
         self.dts = dts
+        self.project = project
 
-        self.querier = ManoQuerier(self.log, self.dts)
-        self.publisher = DescriptorPublisher(self.log, self.loop, self.dts)
+        self.querier = ManoQuerier(self.log, self.dts, self.project)
+        self.publisher = DescriptorPublisher(self.log, self.loop,
+                                             self.dts, self.project)
         self.ping_vnfd, self.pong_vnfd, self.ping_pong_nsd = \
                 ping_pong_nsd.generate_ping_pong_descriptors(
                         pingcount=1,
@@ -717,8 +826,6 @@
                 )
 
 
-
-
 class ManoTestCase(rift.test.dts.AbstractDTSTest):
     """
     DTS GI interface unittests
@@ -755,9 +862,9 @@
     @staticmethod
     def get_cal_account(account_type, account_name):
         """
-        Creates an object for class RwcalYang.Clo
+        Creates an object for class RwcalYang.Cloud
         """
-        account = rwcloudyang.CloudAccount()
+        account = rwcloudyang.CloudAcc()
         if account_type == 'mock':
             account.name          = account_name
             account.account_type  = "mock"
@@ -773,13 +880,33 @@
         return account
 
     @asyncio.coroutine
-    def configure_cloud_account(self, dts, cloud_type, cloud_name="cloud1"):
+    def configure_project(self, project=None):
+        if project is None:
+            project = self.project
+
+        proj_xpath = "C,{}/project-config".format(project.prefix)
+        self.log.info("Creating project: {} with {}".
+                       format(proj_xpath, project.config.as_dict()))
+        xpath_wild = "C,/rw-project:project/project-config"
+        yield from self.project_publisher.publish_project(project.config,
+                                                          proj_xpath,
+                                                          xpath_wild)
+
+    @asyncio.coroutine
+    def configure_cloud_account(self, dts, cloud_type, cloud_name="cloud1", project=None):
         account = self.get_cal_account(cloud_type, cloud_name)
-        account_xpath = "C,/rw-project:project/rw-cloud:cloud/rw-cloud:account[rw-cloud:name='{}']".format(cloud_name)
         self.log.info("Configuring cloud-account: %s", account)
-        yield from dts.query_create(account_xpath,
-                                    rwdts.XactFlag.ADVISE,
-                                    account)
+        if project is None:
+            project = self.project
+        xpath = project.add_project(XPaths.cloud_account(account.name))
+        xpath_wild = project.add_project(XPaths.cloud_account())
+
+        # account_xpath = project.add_project(
+        #     "C,/rw-cloud:cloud/rw-cloud:account[rw-cloud:name='{}']".format(cloud_name))
+        # yield from dts.query_create(account_xpath,
+        #                             rwdts.XactFlag.ADVISE,
+        #                             account)
+        yield from self.cloud_publisher.publish_account(account, xpath, xpath_wild)
 
     @asyncio.coroutine
     def wait_tasklets(self):
@@ -789,22 +916,74 @@
         self.log.debug("STARTING - %s", self.id())
         self.tinfo = self.new_tinfo(self.id())
         self.dts = rift.tasklets.DTS(self.tinfo, self.schema, self.loop)
-        self.ping_pong = PingPongDescriptorPublisher(self.log, self.loop, self.dts)
-        self.querier = ManoQuerier(self.log, self.dts)
+        self.project = ManoProject(self.log,
+                                   name=DEFAULT_PROJECT)
+        self.project1 = ManoProject(self.log,
+                                   name='test-1')
+        self.ping_pong = PingPongDescriptorPublisher(self.log, self.loop,
+                                                     self.dts, self.project)
+        self.querier = ManoQuerier(self.log, self.dts, self.project)
+        self.project_publisher = ProjectPublisher(
+            self.log,
+            loop,
+            self.dts,
+            self.project
+        )
+        self.cloud_publisher = CloudAccountPublisher(
+            self.log,
+            loop,
+            self.dts,
+            self.project
+        )
         self.nsr_publisher = PingPongNsrConfigPublisher(
                 self.log,
                 loop,
                 self.dts,
                 self.ping_pong,
                 "mock_account",
+                self.project,
                 )
 
     def test_create_nsr_record(self):
 
         @asyncio.coroutine
+        def verify_projects(termination=False):
+            self.log.debug("Verifying projects = %s", XPaths.project())
+
+            accts = yield from self.querier._read_query(XPaths.project(),
+                                                        project=False)
+            projs = []
+            for acc in accts:
+                self.log.debug("Project: {}".format(acc.as_dict()))
+                if acc.name not in projs:
+                    projs.append(acc.name)
+            self.log.debug("Merged: {}".format(projs))
+            self.assertEqual(2, len(projs))
+
+        @asyncio.coroutine
+        def verify_cloud_accounts(termination=False):
+            self.log.debug("Verifying cloud accounts = %s", XPaths.cloud_account())
+
+            accts = yield from self.querier._read_query(XPaths.cloud_account())
+            self.assertEqual(2, len(accts))
+
+            accts = yield from self.querier._read_query(
+                self.project1.add_project(XPaths.cloud_account()), project=False)
+            self.assertEqual(1, len(accts))
+
+            accts = yield from self.querier._read_query(
+                "C,/rw-project:project/rw-cloud:cloud/rw-cloud:account",
+                project=False)
+            self.assertEqual(3, len(accts))
+
+            accts = yield from self.querier._read_query(
+                "C,/rw-project:project/rw-cloud:cloud/rw-cloud:account[rw-cloud:name='mock_account']",
+                project=False)
+            self.assertEqual(2, len(accts))
+
+        @asyncio.coroutine
         def verify_cm_state(termination=False, nsrid=None):
             self.log.debug("Verifying cm_state path = %s", XPaths.cm_state(nsrid))
-            #print("###>>> Verifying cm_state path:", XPaths.cm_state(nsrid))
 
             loop_count = 10
             loop_sleep = 10
@@ -878,7 +1057,7 @@
 
             nsr_config = nsr_configs[0]
             self.assertEqual(
-                    "/nsd:nsd-catalog/nsd:nsd[nsd:id={}]/nsd:name".format(self.ping_pong.nsd_id),
+                    "/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id={}]/nsd:name".format(self.ping_pong.nsd_id),
                     nsr_config.input_parameter[0].xpath,
                     )
 
@@ -1031,6 +1210,9 @@
             yield from verify_cm_state(termination, nsrid)
             yield from verify_nsr_config_status(termination, nsrid)
 
+            yield from verify_cloud_account(termination)
+            yield from verify_project_record(termination)
+
         @asyncio.coroutine
         def verify_scale_instance(index):
             self.log.debug("Verifying scale record path = %s, Termination=%d",
@@ -1074,12 +1256,20 @@
         def run_test():
             yield from self.wait_tasklets()
 
+            yield from self.configure_project()
+            yield from self.configure_project(project=self.project1)
 
             cloud_type = "mock"
             yield from self.configure_cloud_account(self.dts, cloud_type, "mock_account")
             yield from self.configure_cloud_account(self.dts, cloud_type, "mock_account1")
+            yield from self.configure_cloud_account(self.dts, cloud_type, "mock_account",
+                                                    project=self.project1)
+
+            yield from verify_cloud_accounts()
+            yield from verify_projects()
 
             yield from self.ping_pong.publish_desciptors()
+            return
 
             # Attempt deleting VNFD not in use
             yield from self.ping_pong.update_ping_vnfd()
diff --git a/rwlaunchpad/test/pytest/lp_kt_utm_test.py b/rwlaunchpad/test/pytest/lp_kt_utm_test.py
index 0a8d6ba..feb0b99 100644
--- a/rwlaunchpad/test/pytest/lp_kt_utm_test.py
+++ b/rwlaunchpad/test/pytest/lp_kt_utm_test.py
@@ -206,7 +206,7 @@
         raise DescriptorOnboardError(state)
 
 def create_nsr_from_nsd_id(nsd_id):
-      nsr = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+      nsr = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
       nsr.id = str(uuid.uuid4())
       nsr.name = "UTM-only"
       nsr.short_name = "UTM-only"
@@ -255,14 +255,14 @@
                        "resource_type": "network",
                        "pool_type" : "dynamic",}]})
 
-        resource_mgr_proxy.merge_config('/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
+        resource_mgr_proxy.merge_config('/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
 
     def test_configure_resource_orchestrator(self, so_proxy):
         cfg = RwConmanYang.RoEndpoint.from_dict({'ro_ip_address': '127.0.0.1',
                                                 'ro_port'      :  2022,
                                                 'ro_username'  : 'admin',
                                                 'ro_password'  : 'admin'})
-        so_proxy.merge_config('/rw-conman:cm-config', cfg)
+        so_proxy.merge_config('/rw-project:project/rw-conman:cm-config', cfg)
 
     def test_configure_service_orchestrator(self, nsm_proxy):
         cfg = RwNsmYang.SoEndpoint.from_dict({'cm_ip_address': '127.0.0.1',
diff --git a/rwlaunchpad/test/pytest/lp_kt_utm_wims_test.py b/rwlaunchpad/test/pytest/lp_kt_utm_wims_test.py
index 9dc9fe2..4e73aac 100644
--- a/rwlaunchpad/test/pytest/lp_kt_utm_wims_test.py
+++ b/rwlaunchpad/test/pytest/lp_kt_utm_wims_test.py
@@ -223,7 +223,7 @@
         raise DescriptorOnboardError(state)
 
 def create_nsr_from_nsd_id(nsd_id):
-      nsr = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+      nsr = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
       nsr.id = str(uuid.uuid4())
       nsr.name = "UTM-WIMS"
       nsr.short_name = "UTM-WIMS"
@@ -272,14 +272,14 @@
                        "resource_type": "network",
                        "pool_type" : "dynamic",}]})
 
-        resource_mgr_proxy.merge_config('/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
+        resource_mgr_proxy.merge_config('/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
 
     def test_configure_resource_orchestrator(self, so_proxy):
         cfg = RwConmanYang.RoEndpoint.from_dict({'ro_ip_address': '127.0.0.1',
                                                 'ro_port'      :  2022,
                                                 'ro_username'  : 'admin',
                                                 'ro_password'  : 'admin'})
-        so_proxy.merge_config('/rw-conman:cm-config', cfg)
+        so_proxy.merge_config('/rw-project:project/rw-conman:cm-config', cfg)
 
     def test_configure_service_orchestrator(self, nsm_proxy):
         cfg = RwNsmYang.SoEndpoint.from_dict({'cm_ip_address': '127.0.0.1',
diff --git a/rwlaunchpad/test/pytest/lp_test.py b/rwlaunchpad/test/pytest/lp_test.py
index b987b35..8b41cb1 100644
--- a/rwlaunchpad/test/pytest/lp_test.py
+++ b/rwlaunchpad/test/pytest/lp_test.py
@@ -172,7 +172,7 @@
 
 
 def create_nsr_from_nsd_id(nsd_id):
-    nsr = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
     nsr.id = str(uuid.uuid4())
     nsr.name = "pingpong_{}".format(datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
     nsr.short_name = "nsr_short_name"
@@ -181,8 +181,8 @@
     nsr.admin_status = "ENABLED"
     nsr.cloud_account = "openstack"
 
-    param = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter()
-    param.xpath = '/nsd:nsd-catalog/nsd:nsd/nsd:vendor'
+    param = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter()
+    param.xpath = '/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:vendor'
     param.value = "rift-o-matic"
 
     nsr.input_parameter.append(param)
diff --git a/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_epa_test.py b/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_epa_test.py
index 8f7334b..3470b75 100644
--- a/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_epa_test.py
+++ b/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_epa_test.py
@@ -172,7 +172,7 @@
 
 
 def create_nsr_from_nsd_id(nsd_id):
-    nsr = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
     nsr.id = str(uuid.uuid4())
     nsr.name = "TG-2Vrouter-TS EPA"
     nsr.short_name = "TG-2Vrouter-TS EPA"
@@ -251,14 +251,14 @@
                        "resource_type": "network",
                        "pool_type" : "dynamic",}]})
 
-        resource_mgr_proxy.merge_config('/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
+        resource_mgr_proxy.merge_config('/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
 
     def test_configure_resource_orchestrator(self, so_proxy):
         cfg = RwConmanYang.RoEndpoint.from_dict({'ro_ip_address': '127.0.0.1',
                                                 'ro_port'      :  2022,
                                                 'ro_username'  : 'admin',
                                                 'ro_password'  : 'admin'})
-        so_proxy.merge_config('/rw-conman:cm-config', cfg)
+        so_proxy.merge_config('/rw-project:project/rw-conman:cm-config', cfg)
 
     def test_configure_service_orchestrator(self, nsm_proxy):
         cfg = RwNsmYang.SoEndpoint.from_dict({'cm_ip_address': '127.0.0.1',
diff --git a/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_test.py b/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_test.py
index c2f27a7..578c0af 100644
--- a/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_test.py
+++ b/rwlaunchpad/test/pytest/lp_tg_2vrouter_ts_test.py
@@ -172,7 +172,7 @@
 
 
 def create_nsr_from_nsd_id(nsd_id):
-    nsr = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
     nsr.id = str(uuid.uuid4())
     nsr.name = "TG-2Vrouter-TS EPA"
     nsr.short_name = "TG-2Vrouter-TS EPA"
@@ -251,14 +251,14 @@
                        "resource_type": "network",
                        "pool_type" : "dynamic",}]})
 
-        resource_mgr_proxy.merge_config('/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
+        resource_mgr_proxy.merge_config('/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
 
     def test_configure_resource_orchestrator(self, so_proxy):
         cfg = RwConmanYang.RoEndpoint.from_dict({'ro_ip_address': '127.0.0.1',
                                                 'ro_port'      :  2022,
                                                 'ro_username'  : 'admin',
                                                 'ro_password'  : 'admin'})
-        so_proxy.merge_config('/rw-conman:cm-config', cfg)
+        so_proxy.merge_config('/rw-project:project/rw-conman:cm-config', cfg)
 
     def test_configure_service_orchestrator(self, nsm_proxy):
         cfg = RwNsmYang.SoEndpoint.from_dict({'cm_ip_address': '127.0.0.1',
diff --git a/rwlaunchpad/test/pytest/lp_tg_vrouter_ts_epa_sriov_test.py b/rwlaunchpad/test/pytest/lp_tg_vrouter_ts_epa_sriov_test.py
index c851847..405bee6 100644
--- a/rwlaunchpad/test/pytest/lp_tg_vrouter_ts_epa_sriov_test.py
+++ b/rwlaunchpad/test/pytest/lp_tg_vrouter_ts_epa_sriov_test.py
@@ -171,7 +171,7 @@
 
 
 def create_nsr_from_nsd_id(nsd_id):
-    nsr = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+    nsr = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
     nsr.id = str(uuid.uuid4())
     nsr.name = "TG-Vrouter-TS-EPA-SRIOV"
     nsr.short_name = "TG-Vrouter-TS-EPA-SRIOV"
@@ -250,14 +250,14 @@
                        "resource_type": "network",
                        "pool_type" : "dynamic",}]})
 
-        resource_mgr_proxy.merge_config('/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
+        resource_mgr_proxy.merge_config('/rw-project:project/rw-resource-mgr:resource-mgr-config/rw-resource-mgr:resource-pools', pools)
 
     def test_configure_resource_orchestrator(self, so_proxy):
         cfg = RwConmanYang.RoEndpoint.from_dict({'ro_ip_address': '127.0.0.1',
                                                 'ro_port'      :  2022,
                                                 'ro_username'  : 'admin',
                                                 'ro_password'  : 'admin'})
-        so_proxy.merge_config('/rw-conman:cm-config', cfg)
+        so_proxy.merge_config('/rw-project:project/rw-conman:cm-config', cfg)
 
     def test_configure_service_orchestrator(self, nsm_proxy):
         cfg = RwNsmYang.SoEndpoint.from_dict({'cm_ip_address': '127.0.0.1',
diff --git a/rwlaunchpad/test/utest_nsr_handler.py b/rwlaunchpad/test/utest_nsr_handler.py
index ffab929..d921aca 100755
--- a/rwlaunchpad/test/utest_nsr_handler.py
+++ b/rwlaunchpad/test/utest_nsr_handler.py
@@ -47,8 +47,8 @@
 
 class NsrDtsHandler(object):
     """ The network service DTS handler """
-    NSR_XPATH = "C,/nsr:ns-instance-config/nsr:nsr"
-    SCALE_INSTANCE_XPATH = "C,/nsr:ns-instance-config/nsr:nsr/nsr:scaling-group/nsr:instance"
+    NSR_XPATH = "C,/rw-project:project/nsr:ns-instance-config/nsr:nsr"
+    SCALE_INSTANCE_XPATH = "C,/rw-project:project/nsr:ns-instance-config/nsr:nsr/nsr:scaling-group/nsr:instance"
 
     def __init__(self, dts, log, loop, nsm):
         self._dts = dts
@@ -66,12 +66,12 @@
 
     def get_scale_group_instances(self, nsr_id, group_name):
         def nsr_id_from_keyspec(ks):
-            nsr_path_entry = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr.schema().keyspec_to_entry(ks)
+            nsr_path_entry = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr.schema().keyspec_to_entry(ks)
             nsr_id = nsr_path_entry.key00.id
             return nsr_id
 
         def group_name_from_keyspec(ks):
-            group_path_entry = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup.schema().keyspec_to_entry(ks)
+            group_path_entry = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup.schema().keyspec_to_entry(ks)
             group_name = group_path_entry.key00.scaling_group_name_ref
             return group_name
 
@@ -95,12 +95,12 @@
         """ Register for Nsr create/update/delete/read requests from dts """
 
         def nsr_id_from_keyspec(ks):
-            nsr_path_entry = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr.schema().keyspec_to_entry(ks)
+            nsr_path_entry = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr.schema().keyspec_to_entry(ks)
             nsr_id = nsr_path_entry.key00.id
             return nsr_id
 
         def group_name_from_keyspec(ks):
-            group_path_entry = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup.schema().keyspec_to_entry(ks)
+            group_path_entry = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup.schema().keyspec_to_entry(ks)
             group_name = group_path_entry.key00.scaling_group_name_ref
             return group_name
 
@@ -327,11 +327,11 @@
 class XPaths(object):
     @staticmethod
     def nsr_config(nsr_id=None):
-        return ("C,/nsr:ns-instance-config/nsr:nsr" +
+        return ("C,/rw-project:project/nsr:ns-instance-config/nsr:nsr" +
                 ("[nsr:id='{}']".format(nsr_id) if nsr_id is not None else ""))
 
     def scaling_group_instance(nsr_id, group_name, instance_id):
-        return ("C,/nsr:ns-instance-config/nsr:nsr" +
+        return ("C,/rw-project:project/nsr:ns-instance-config/nsr:nsr" +
                 "[nsr:id='{}']".format(nsr_id) +
                 "/nsr:scaling-group" +
                 "[nsr:scaling-group-name-ref='{}']".format(group_name) +
@@ -377,7 +377,7 @@
             block = xact.block_create()
             block.add_query_update(
                 XPaths.nsr_config(nsr1_uuid),
-                NsrYang.YangData_Nsr_NsInstanceConfig_Nsr(id=nsr1_uuid, name="fu"),
+                NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr(id=nsr1_uuid, name="fu"),
                 flags=rwdts.XactFlag.ADVISE | rwdts.XactFlag.TRACE,
                 )
             yield from block.execute(now=True)
@@ -388,7 +388,7 @@
             block = xact.block_create()
             block.add_query_update(
                     XPaths.scaling_group_instance(nsr1_uuid, "group", 1234),
-                    NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup_Instance(id=1234),
+                    NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup_Instance(id=1234),
                     flags=rwdts.XactFlag.ADVISE | rwdts.XactFlag.TRACE,
                     )
             yield from block.execute(now=True)
@@ -409,7 +409,7 @@
             block = xact.block_create()
             block.add_query_create(
                     XPaths.scaling_group_instance(nsr1_uuid, "group", 12345),
-                    NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_ScalingGroup_Instance(id=12345),
+                    NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_ScalingGroup_Instance(id=12345),
                     flags=rwdts.XactFlag.ADVISE | rwdts.XactFlag.TRACE,
                     )
             yield from block.execute(now=True)
@@ -427,7 +427,7 @@
             block = xact.block_create()
             block.add_query_update(
                 XPaths.nsr_config(nsr2_uuid),
-                NsrYang.YangData_Nsr_NsInstanceConfig_Nsr(id=nsr2_uuid, name="fu2"),
+                NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr(id=nsr2_uuid, name="fu2"),
                 flags=rwdts.XactFlag.ADVISE | rwdts.XactFlag.TRACE,
                 )
             yield from block.execute(now=True)
diff --git a/rwlaunchpad/test/utest_ro_account.py b/rwlaunchpad/test/utest_ro_account.py
index aa485ef..9ed28fd 100755
--- a/rwlaunchpad/test/utest_ro_account.py
+++ b/rwlaunchpad/test/utest_ro_account.py
@@ -115,7 +115,7 @@
                 {'name': 'rift-ro', 'account_type': 'rift_ro', 'rift_ro': {'rift_ro': True}})
 
         # Test rift-ro plugin CREATE
-        w_xpath = "C,/rw-launchpad:resource-orchestrator"
+        w_xpath = "C,/rw-project:project/rw-launchpad:resource-orchestrator"
         xpath = w_xpath
         yield from self.publisher.publish(w_xpath, xpath, mock_orch_acc)
         yield from asyncio.sleep(5, loop=self.loop)
@@ -139,7 +139,7 @@
         # Test update
         mock_orch_acc.openmano.port = 9789
         mock_orch_acc.openmano.host = "10.64.11.78"
-        yield from self.dts.query_update("C,/rw-launchpad:resource-orchestrator",
+        yield from self.dts.query_update("C,/rw-project:project/rw-launchpad:resource-orchestrator",
                 rwdts.XactFlag.ADVISE, mock_orch_acc)
         assert orch.ro_plugin._cli_api._port  == mock_orch_acc.openmano.port
         assert orch.ro_plugin._cli_api._host  == mock_orch_acc.openmano.host
@@ -150,11 +150,11 @@
         mock_orch_acc.openmano.port = 9788
 
         with self.assertRaises(Exception):
-            yield from self.dts.query_update("C,/rw-launchpad:resource-orchestrator",
+            yield from self.dts.query_update("C,/rw-project:project/rw-launchpad:resource-orchestrator",
                     rwdts.XactFlag.ADVISE, mock_orch_acc)
 
         # Test delete
-        yield from self.dts.query_delete("C,/rw-launchpad:resource-orchestrator",
+        yield from self.dts.query_delete("C,/rw-project:project/rw-launchpad:resource-orchestrator",
                 flags=rwdts.XactFlag.ADVISE)
         assert orch.ro_plugin == None
 
diff --git a/rwlaunchpad/test/utest_rwmonitor.py b/rwlaunchpad/test/utest_rwmonitor.py
index 46c33b3..91f162f 100755
--- a/rwlaunchpad/test/utest_rwmonitor.py
+++ b/rwlaunchpad/test/utest_rwmonitor.py
@@ -108,17 +108,17 @@
 
 
 def make_nsr(ns_instance_config_ref=str(uuid.uuid4())):
-    nsr = NsrYang.YangData_Nsr_NsInstanceOpdata_Nsr()
+    nsr = NsrYang.YangData_RwProject_Project_NsInstanceOpdata_Nsr()
     nsr.ns_instance_config_ref = ns_instance_config_ref
     return nsr
 
 def make_vnfr(id=str(uuid.uuid4())):
-    vnfr = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
+    vnfr = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr()
     vnfr.id = id
     return vnfr
 
 def make_vdur(id=str(uuid.uuid4()), vim_id=str(uuid.uuid4())):
-    vdur = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
+    vdur = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur()
     vdur.id = id
     vdur.vim_id = vim_id
     return vdur
@@ -149,7 +149,7 @@
         mock = self.plugin_manager.plugin(self.account.name)
         mock.set_impl(TestNfviMetricsCache.Plugin())
 
-        self.vdur = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
+        self.vdur = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur()
         self.vdur.id = "test-vdur-id"
         self.vdur.vim_id = "test-vim-id"
         self.vdur.vm_flavor.vcpu_count = 4
@@ -207,7 +207,7 @@
             return True
 
         def nfvi_metrics(self, account, vim_id):
-            metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
+            metrics = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
             metrics.vcpu.utilization = 0.5
             return None, metrics
 
@@ -340,7 +340,7 @@
         pass
 
     def test_alarm_create_and_destroy(self):
-        alarm = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_Alarms()
+        alarm = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_Alarms()
         alarm.name = "test-alarm"
         alarm.description = "test-description"
         alarm.vdur_id = "test-vdur-id"
@@ -606,7 +606,7 @@
         self.monitor.add_cloud_account(self.account)
 
         # Create a VNFR associated with the cloud account
-        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
+        vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr()
         vnfr.cloud_account = self.account.name
         vnfr.id = 'test-vnfr-id'
 
@@ -644,7 +644,7 @@
         to retrieve the NFVI metrics associated with the VDU.
         """
         # Define the VDUR to be registered
-        vdur = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
+        vdur = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur()
         vdur.vm_flavor.vcpu_count = 4
         vdur.vm_flavor.memory_mb = 100
         vdur.vm_flavor.storage_gb = 2
@@ -680,11 +680,11 @@
         the VDURs contained in the VNFR are unregistered.
         """
         # Define the VDUR to be registered
-        vdur = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
+        vdur = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur()
         vdur.vim_id = 'test-vim-id-1'
         vdur.id = 'test-vdur-id-1'
 
-        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
+        vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr()
         vnfr.cloud_account = self.account.name
         vnfr.id = 'test-vnfr-id'
 
@@ -699,7 +699,7 @@
 
         # Add another VDUR to the VNFR and update the monitor. Both VDURs
         # should now be registered
-        vdur = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
+        vdur = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur()
         vdur.vim_id = 'test-vim-id-2'
         vdur.id = 'test-vdur-id-2'
 
@@ -730,7 +730,7 @@
         Monitor.
         """
         # Create the VNFR
-        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
+        vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr()
         vnfr.cloud_account = self.account.name
         vnfr.id = 'test-vnfr-id'
 
diff --git a/rwlaunchpad/test/utest_rwnsm.py b/rwlaunchpad/test/utest_rwnsm.py
index e125739..fa99751 100755
--- a/rwlaunchpad/test/utest_rwnsm.py
+++ b/rwlaunchpad/test/utest_rwnsm.py
@@ -46,18 +46,18 @@
 
         """
         # Create the initial NSD catalog
-        nsd_catalog = NsdYang.YangData_Nsd_NsdCatalog()
+        nsd_catalog = NsdYang.YangData_RwProject_Project_NsdCatalog()
 
         # Create an NSD, set its 'id', and add it to the catalog
         nsd_id = str(uuid.uuid4())
         nsd_catalog.nsd.append(
-                NsdYang.YangData_Nsd_NsdCatalog_Nsd(
+                NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd(
                     id=nsd_id,
                     )
                 )
 
         # Retrieve the NSD using and xpath expression
-        xpath = '/nsd:nsd-catalog/nsd:nsd[nsd:id={}]'.format(nsd_id)
+        xpath = '/rw-project:project/nsd:nsd-catalog/nsd:nsd[nsd:id={}]'.format(nsd_id)
         nsd = rwxpath.getxattr(nsd_catalog, xpath)
 
         self.assertEqual(nsd_id, nsd.id)
@@ -74,19 +74,19 @@
 
         """
         # Define a simple NSD
-        nsd = NsdYang.YangData_Nsd_NsdCatalog_Nsd()
+        nsd = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd()
 
         # Check that the unset fields are in fact set to None
-        self.assertEqual(None, rwxpath.getxattr(nsd, "/nsd:nsd-catalog/nsd:nsd/nsd:name"))
-        self.assertEqual(None, rwxpath.getxattr(nsd, "/nsd:nsd-catalog/nsd:nsd/nsd:short-name"))
+        self.assertEqual(None, rwxpath.getxattr(nsd, "/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name"))
+        self.assertEqual(None, rwxpath.getxattr(nsd, "/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:short-name"))
 
         # Set the values of the 'name' and 'short-name' fields
-        rwxpath.setxattr(nsd, "/nsd:nsd-catalog/nsd:nsd/nsd:name", "test-name")
-        rwxpath.setxattr(nsd, "/nsd:nsd-catalog/nsd:nsd/nsd:short-name", "test-short-name")
+        rwxpath.setxattr(nsd, "/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name", "test-name")
+        rwxpath.setxattr(nsd, "/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:short-name", "test-short-name")
 
         # Check that the 'name' and 'short-name' fields are correctly set
-        self.assertEqual(nsd.name, rwxpath.getxattr(nsd, "/nsd:nsd-catalog/nsd:nsd/nsd:name"))
-        self.assertEqual(nsd.short_name, rwxpath.getxattr(nsd, "/nsd:nsd-catalog/nsd:nsd/nsd:short-name"))
+        self.assertEqual(nsd.name, rwxpath.getxattr(nsd, "/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name"))
+        self.assertEqual(nsd.short_name, rwxpath.getxattr(nsd, "/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:short-name"))
 
 
 class TestInputParameterSubstitution(unittest.TestCase):
@@ -99,8 +99,8 @@
         config, no exception should be raised.
 
         """
-        nsd = NsdYang.YangData_Nsd_NsdCatalog_Nsd()
-        nsr_config = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+        nsd = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd()
+        nsr_config = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
 
         self.substitute_input_parameters(None, None)
         self.substitute_input_parameters(nsd, None)
@@ -115,27 +115,27 @@
 
         """
         # Define the original NSD
-        nsd = NsdYang.YangData_Nsd_NsdCatalog_Nsd()
+        nsd = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd()
         nsd.name = "robert"
         nsd.short_name = "bob"
 
         # Define which parameters may be modified
         nsd.input_parameter_xpath.append(
-                NsdYang.YangData_Nsd_NsdCatalog_Nsd_InputParameterXpath(
-                    xpath="/nsd:nsd-catalog/nsd:nsd/nsd:name",
+                NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_InputParameterXpath(
+                    xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name",
                     label="NSD Name",
                     )
                 )
 
         # Define the input parameters that are intended to be modified
-        nsr_config = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+        nsr_config = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
         nsr_config.input_parameter.extend([
-            NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
-                xpath="/nsd:nsd-catalog/nsd:nsd/nsd:name",
+            NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
+                xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name",
                 value="alice",
                 ),
-            NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
-                xpath="/nsd:nsd-catalog/nsd:nsd/nsd:short-name",
+            NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
+                xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:short-name",
                 value="alice",
                 ),
             ])
@@ -153,31 +153,31 @@
 
         """
         # Define the original NSD
-        nsd = NsdYang.YangData_Nsd_NsdCatalog_Nsd()
+        nsd = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd()
         nsd.name = "robert"
         nsd.short_name = "bob"
 
         # Define which parameters may be modified
         nsd.input_parameter_xpath.extend([
-                NsdYang.YangData_Nsd_NsdCatalog_Nsd_InputParameterXpath(
-                    xpath="/nsd:nsd-catalog/nsd:nsd/nsd:name",
+                NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_InputParameterXpath(
+                    xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name",
                     label="NSD Name",
                     ),
-                NsdYang.YangData_Nsd_NsdCatalog_Nsd_InputParameterXpath(
-                    xpath="/nsd:nsd-catalog/nsd:nsd/nsd:short-name",
+                NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_InputParameterXpath(
+                    xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:short-name",
                     label="NSD Short Name",
                     ),
                 ])
 
         # Define the input parameters that are intended to be modified
-        nsr_config = NsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
+        nsr_config = NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
         nsr_config.input_parameter.extend([
-            NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
-                xpath="/nsd:nsd-catalog/nsd:nsd/nsd:name",
+            NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
+                xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:name",
                 value="robert",
                 ),
-            NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
-                xpath="/nsd:nsd-catalog/nsd:nsd/nsd:short-name",
+            NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
+                xpath="/rw-project:project/nsd:nsd-catalog/nsd:nsd/nsd:short-name",
                 value="bob",
                 ),
             ])