def delete_single(nsd_info_id):
     ns_pkgs = NSPackageModel.objects.filter(nsPackageId=nsd_info_id)
     if not ns_pkgs.exists():
+        logger.debug('NS descriptor (%s) is deleted.' % nsd_info_id)
         return
     if ns_pkgs[0].onboardingState == 'ONBOARDED':
         raise CatalogException('The NS descriptor (%s) shall be non-ONBOARDED.' % nsd_info_id)
     if ns_pkgs[0].usageState != 'NOT_IN_USE':
         raise CatalogException('The NS descriptor (%s) shall be NOT_IN_USE.' % nsd_info_id)
     ns_pkgs.delete()
+    ns_pkg_path = os.path.join(CATALOG_ROOT_PATH, nsd_info_id)
+    fileutil.delete_dirs(ns_pkg_path)
+    logger.debug('NS descriptor (%s) is deleted.' % nsd_info_id)
 
 
 def process(nsd_info_id, local_file_name):
 
 from catalog.pub.config.config import CATALOG_ROOT_PATH
 from catalog.pub.utils import fileutil
 from catalog.pub.utils.values import ignore_case_get
-from catalog.pub.database.models import PnfPackageModel
+from catalog.pub.database.models import NSPackageModel, PnfPackageModel
 from catalog.pub.exceptions import CatalogException
 from catalog.pub.utils import toscaparser
 
 
 def delete_pnf(pnfd_info_id):
     # TODO
-    pnf_pkg = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
-    if not pnf_pkg.exists():
-        logger.debug('PNF resource(%s) is deleted.' % pnfd_info_id)
+    pnf_pkgs = PnfPackageModel.objects.filter(pnfPackageId=pnfd_info_id)
+    if not pnf_pkgs.exists():
+        logger.debug('PNF descriptor (%s) is deleted.' % pnfd_info_id)
         return
-    pnf_pkg.delete()
+    if pnf_pkgs[0].usageState != 'NOT_IN_USE':
+        raise CatalogException('The PNF descriptor (%s) shall be NOT_IN_USE.' % pnfd_info_id)
+    ns_pkgs = NSPackageModel.objects.all()
+    for ns_pkg in ns_pkgs:
+        if pnfd_info_id in ns_pkg.pnfdInfoIds:
+            raise CatalogException('The PNF descriptor (%s) is referenced.' % pnfd_info_id)
+            break
+    pnf_pkgs.delete()
     vnf_pkg_path = os.path.join(CATALOG_ROOT_PATH, pnfd_info_id)
     fileutil.delete_dirs(vnf_pkg_path)
+    logger.debug('PNF descriptor (%s) is deleted.' % pnfd_info_id)
 
 
 def fill_response_data(pnf_pkg):
 
         self.assertEqual(expected_reponse_data, response.data)
 
     def test_delete_single_pnfd_normal(self):
-        pass
+        user_defined_data = {
+            'key1': 'value1',
+            'key2': 'value2',
+            'key3': 'value3',
+        }
+        user_defined_data = json.JSONEncoder().encode(user_defined_data)
+        PnfPackageModel(
+            pnfPackageId='22',
+            usageState='NOT_IN_USE',
+            userDefinedData=user_defined_data,
+            pnfdModel='test'
+        ).save()
+        resp = self.client.delete("/api/nsd/v1/pnf_descriptors/22", format='json')
+        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
+        self.assertEqual(None, resp.data)
 
     def test_pnfd_content_upload_normal(self):
         user_defined_data_json = json.JSONEncoder().encode(self.user_defined_data)